modello per sbloccare thread e ottenere variabili in sblocco veloce

0

Ho una discussione che va in loop facendo qualcosa del genere

void thread()
{
  pthread_mutex_lock(mutex);

  for ( ; ; )
  {
    /** code **/
    {
      pthread_mutex_unlock(mutex);
      /** do_something **/
      pthread_mutex_lock(mutex);
    }

    if (exit)
      return;
  }
}

dove exit verrà aggiornato in un thread diverso per true, se necessario. Il mio problema è che funziona bene quando do_something richiede un po 'di tempo, ma se non lo fa l'altro thread non riavrà mai il mutex. O ci vuole troppo tempo per farlo.

Qual è lo schema corretto in una situazione come questa?

    
posta cauchy 13.11.2017 - 09:35
fonte

2 risposte

4

Il problema di base qui sembra essere che questo thread mantiene il mutex bloccato per impostazione predefinita e lo sblocca solo per un periodo di tempo limitato quando è sicuro che non sia necessario al mutex.

Normalmente, si vuole fare all'incirca il contrario: il mutex è sbloccato di default e viene bloccato solo per un breve periodo di tempo quando assolutamente necessario. Senza conoscere almeno un po 'del resto del codice, però, è difficile essere sicuri del modo giusto per farlo.

Una possibilità sarebbe quella di ristrutturare il codice in modo che solo un singolo thread debba trattare direttamente con le risorse condivise e gli altri due thread abbiano una coda di richieste che inviano a quel thread. Quel thread può quindi dare la priorità alle richieste, in modo che entrambi i thread client ottengano le stesse possibilità di fare le loro cose con le risorse condivise (o forse non necessariamente uguali, ma una quantità appropriata per ciascuna).

Per inciso, se non puoi usare le classi di threading C ++ 11, dovrei almeno prendere in considerazione la scrittura di analogici approssimativi - una classe mutex che chiama pthread_mutex_create nel suo ctor, pthread_mutex_destroy nel suo dtor, e ha un lock e unlock che chiamano rispettivamente pthread_mutex_lock e pthread_mutex_unlock .

Allo stesso modo, un lock_guard ha passato un mutex che blocca nel suo ctor, e sblocca nel suo dtor (e possibilmente un wrapper simile per variabili di condizione, ecc.) Linea di fondo: se stai partendo da pthreads, tu è in grado di scrivere un sottogruppo piuttosto consistente del threading della libreria standard abbastanza rapidamente e facilmente.

Entrambi sono abbastanza banali e semplificano il resto del codice abbastanza che il tempo per svilupparli verrà ripagato abbastanza rapidamente. Inoltre, ti daranno cose come la sicurezza delle eccezioni che sono molto più difficili da implementare nella maggior parte degli altri modi.

    
risposta data 13.11.2017 - 20:51
fonte
4

In questa funzione, blocchi il mutex e tieni il blocco bloccato tranne che per una piccola parte, dove do_something , lasciando che gli altri thread acquisiscano il mutex, prima di aspettare di bloccarlo nuovamente.

Cosa c'è che non va?

  1. Quando exit è true, il thread termina, lasciando mutex bloccato e bloccando tutti gli altri thread in attesa di acquisirlo. Forse è apposta, ma per me sembra piuttosto sospetto (specialmente se hai qualche pthread_join() da qualche parte).

  2. La funzione non sembra eccezionalmente sicura, per un motivo simile: se un'eccezione si verifica in /* code */ , causerebbe il blocco di mutex e il processo rimane bloccato per sempre a causa degli altri thread in attesa di %codice%. mutex offre std::thread come wrapper che si assicura in base a RAII principio che il blocco viene rimosso se la guardia viene distrutta per esempio a causa dello stack di svolgimento.

  3. A seconda di lock_guard , gli altri thread in attesa di acquisire do_something potrebbero starve (ad es. nessun altro thread ottiene l'opportunità di acquisire il lock, o sempre lo stesso ottiene il lock a spese di tutti gli altri, ecc ...).

Come farlo bene?

Non è facile con il litle che conosciamo per darti il miglior consiglio. Tuttavia, a prima vista, sembra che si possa pensare di utilizzare un altro meccanismo di sincronizzazione, le variabili di condizione. Esiste come mutex se si utilizzano i thread standard. Ma esistono anche per i pthreads, come spiegato in dettaglio in questo articolo .

Per farla breve, le variabili di condizione fanno qualcosa di simile al tuo codice: diversi thread sono in attesa con std::condition_variable per un evento pubblicizzato utilizzando una variabile di condizione. Un thread riattiva i thread in attesa con pthread_cond_wait() o pthread_cond_broadcast() . Uno dei thread ottiene il controllo con il mutex bloccato.

    
risposta data 13.11.2017 - 19:24
fonte

Leggi altre domande sui tag