Supponendo che stai usando pthreads, devi essere consapevole che i lock sono implementati come funzioni e macro.
Ciò significa che un lock non rende una variabile disponibile o meno a una CPU, né inviano operazioni alle CPU dell'altra (s). Quello che fai è generare i thread, chiamando pthread_create()
con un puntatore a funzione come parametro. In genere vengono generati più thread con la stessa funzione e diversi parametri, quindi ognuno esegue lo stesso codice in modo leggermente diverso.
Idealmente, la maggior parte del codice dovrebbe funzionare su dati diversi, allocando blocchi privati in modo che ogni thread possa essere eseguito senza verificare le collisioni.
Naturalmente, c'è sempre qualche parte condivisa, o una comunicazione tra thread, o una struttura di un negozio comune. Per questo usi i blocchi.
In breve, ogni risorsa condivisa deve avere un blocco e prima di provare ad accedere alla risorsa devi acquisire il blocco usando pthread_mutex_lock()
o una funzione simile e rilasciarlo con pthread_mutex_unlock()
subito dopo aver usato la risorsa.
Quando nessun altro thread stava tentando di utilizzare la stessa risorsa, queste funzioni ritornano rapidamente e il codice può fare come previsto. Ma se un thread tenta di ottenere un blocco mentre un altro lo ha già, il secondo viene bloccato e non può continuare finché il primo non lo rilascia.
In breve, circondare del codice con chiamate di blocco / sblocco garantisce che solo una discussione gestirà quella parte del codice con quel blocco specifico in un dato momento.
Quello che vuoi fare per ottimizzare la concorrenza del tuo codice è quello di tenere i blocchi per il minor numero possibile di operazioni, nel minor tempo possibile e con la più specifica (diversi blocchi per diverse strutture di dati, anche se il codice è comune ).
Oltre a questo, devi essere consapevole di deadlock, livelock, inversioni di priorità, ecc. Ma solo assicurarti che ogni struttura condivisa abbia un blocco associato (ed è usata in modo coerente!) è un buon inizio.
Incapsulare il blocco con la struttura condivisa e utilizzare solo le funzioni di accesso che rafforzano il blocco rende molto più facile da eseguire correttamente.