2010-10-20 17 views
16

Ho letto sul multithreading e accesso alle risorse condivise e uno dei molti (per me) nuovi concetti è il blocco mutex. Quello che non riesco a scoprire è ciò che sta realmente accadendo al thread che trova una "sezione critica" bloccata. Dice in molti punti che il thread viene "bloccato", ma cosa significa? È sospeso e riprenderà quando si solleverà la serratura? Oppure riproverà nella successiva iterazione del "ciclo di esecuzione"?Blocco mutex: cosa significa "blocco"?

La ragione per cui chiedo è perché voglio che gli eventi forniti dal sistema (mouse, tastiera, ecc.), Che (apparentemente) siano consegnati sul thread principale, vengano gestiti in una parte molto specifica del ciclo di esecuzione del mio filo secondario. Quindi, qualunque sia l'evento consegnato, faccio la fila nella mia stessa infrastruttura. Ovviamente, la struttura dati ha bisogno di un blocco mutex perché è stata modificata da entrambi i thread. Il pezzo mancante del puzzle è: cosa succede quando un evento viene consegnato in una funzione sul thread principale, voglio accodarlo, ma la coda è bloccata? Il thread principale sarà sospeso o salterà sopra la sezione bloccata e uscirà dall'ambito (perdendo l'evento)?

risposta

11

Bloccato significa che l'esecuzione viene bloccata lì; generalmente, il thread viene messo in sospensione dal sistema e restituisce il processore a un altro thread. Quando un thread è bloccato cercando di acquisire un mutex, l'esecuzione riprende quando viene rilasciato il mutex, anche se il thread potrebbe bloccarsi di nuovo se un altro thread afferra il mutex prima che possa farlo.

C'è generalmente un'operazione try-lock che cattura se possibile il mutex e, in caso contrario, restituirà un errore. Ma alla fine dovrai spostare l'evento corrente in quella coda. Inoltre, se si ritardano lo spostamento degli eventi nel thread in cui vengono gestiti, l'applicazione non risponderà in alcun modo.

Una coda è in realtà un caso in cui è possibile evitare di utilizzare un mutex. Ad esempio, Mac OS X (e possibilmente anche iOS) fornisce le funzioni OSAtomicEnqueue() e OSAtomicDequeue() (vedere man atomic o <libkern/OSAtomic.h>) che sfruttano le operazioni atomiche specifiche del processore per evitare l'uso di un blocco.

Ma perché non elaborare gli eventi sul thread principale come parte del ciclo di esecuzione principale?

+0

Il ciclo di esecuzione principale non è quello che guida l'applicazione. Sono su Mac OSX e uso un CVDisplayLink che genera in effetti un thread separato (ad alta priorità) che a sua volta guiderà il mio ciclo di esecuzione. Gli eventi, a quanto ho capito, verranno pubblicati sul thread principale, quindi la sincronizzazione sembra in ordine. – zmippie

1

Il blocco significa proprio questo. È bloccato Non procederà finché non sarà in grado. Non si dice quale lingua si sta utilizzando, ma la maggior parte delle lingue/librerie hanno oggetti di blocco in cui è possibile "tentare" di prendere il blocco e quindi proseguire e fare qualcosa di diverso a seconda che si sia riusciti o meno.

Ma, ad esempio, nei blocchi sincronizzati Java, il thread si bloccherà fino a quando non sarà in grado di acquisire il monitor (mutex, blocco). L'interfaccia java.util.concurrent.locks.Lock descrive gli oggetti di blocco che hanno maggiore flessibilità in termini di acquisizione del blocco.

6

Il modo più semplice per pensarci è che il thread bloccato viene messo in attesa ("dormendo") finché il mutex non viene rilasciato dal thread che lo contiene. A quel punto il sistema operativo "sveglierà" uno dei thread in attesa sul mutex e lascerà che lo acquisisca e continui. È come se il sistema operativo semplicemente mettesse il thread bloccato su uno scaffale fino a che non avesse la cosa di cui ha bisogno per continuare. Fino a quando il sistema operativo non prende il thread dallo scaffale, non sta facendo nulla. L'esatta implementazione - quale thread andrà dopo, se vengono tutti risvegliati o in coda - dipenderà dal tuo SO e dalla lingua/framework che stai usando.

+0

Quindi, qual è esattamente la differenza nell'essere bloccati o in attesa, sono la stessa cosa? – Celeritas

0

Troppo tardi per rispondere ma posso facilitare la comprensione. Sto parlando più dalla prospettiva di implementazione che dai testi teorici.

La parola "blocco" è una specie di omonimo tecnico.Le persone possono usarlo per dormire o semplicemente in attesa. Il termine deve essere compreso nel contesto dell'uso.

mezzi di bloccaggio attesa - supponga su un sistema SMP un filo A desidera acquisire uno spinlock tenuta da un altro filo B. Uno dei meccanismi è quello di disattivare prelazione e mantenere gira sul processore meno B ottiene. Un altro meccanismo, probabilmente, efficiente, è quello di consentire ad altri thread di utilizzare il processore, nel caso in cui B non lo ottenga in facili tentativi. Quindi pianifichiamo il thread B (dato che il preemption è abilitato) e assegniamo il processore ad un altro thread C. In questo caso il thread B attende nella coda dello scheduler e ritorna con il suo turno. Comprendi che B non sta dormendo solo aspettando piuttosto passivamente invece di busy-wait e bruciando i cicli del processore. Sui sistemi BSD e Solaris ci sono strutture dati come i tornelli per implementare questa situazione.

mezzi di bloccaggio pelo - Se il filo B aveva invece fatto chiamata di sistema come read() attesa dati dalla presa di rete, non può procedere fino a quando l'ottiene. Pertanto, alcuni testi usano casualmente il blocco dei termini come "... bloccato per I/O" o "... in blocco per la chiamata di sistema". In realtà, il thread B è piuttosto dormiente. Esistono strutture dati specifiche note come code di attesa - molto simili a sale d'attesa di lusso in aeroporto :-). Il thread verrà riattivato quando il sistema operativo rileva la disponibilità dei dati, proprio come un addetto alla sala d'attesa.

Problemi correlati