Concorrente Java: ReentrantLock ha un design errato?

0

So che ReentrantLock utilizzare AbstractQueuedSynchronizer ( AQS ) per implementare Blocca . Ma il dettaglio della realizzazione, non riesco a capire.

So che AQS usa volatile, CAS e gira per la sincronizzazione. Ma queste azioni controllano solo il membro "stato".

Sebbene LockSupport.park e LockSupport.unpark possano sincronizzare la linea del thread. Ma se non ci sono mai contese, i metodi LockSupport non verranno mai chiamati. Come questo: 1.Thread A start ed esegui

2.Thread B inizia ed esegue

3.Thread A:

lock.lock();
try{
  //modify some shared members
  ....
}finally{
  lock.unlock();
}

4.Then Thread B:

lock.lock();
try{
  //read shared members
  ....
}finally{
  lock.unlock();
}

Nessuna contesa, il thread B non chiama i metodi LockSupport .

lock.lock () solo CAS membro "stato" e lock.unlock () modifica lo "stato" volatile su 0 .

Perché il thread B può vedere la modifica del thread A sui membri condivisi?

Perché ReentrantLock può essere utilizzato come "sincronizzato"?

Non ho visto alcun codice come fullFence per sincronizzare la memoria.

Quale codice realizza la sincronizzazione della cacheline del thread?

Ho visto il codice sorgente in Android art vm e HotSpot vm.

In Android:

Utilizza std :: atomic - > compare_exchange_strong e Heap :: WriteBarrierField. Questi funziona come solo modificare un campo, non tutte le linee di caching di un thread.

In HotSpot:

Utilizza Atomic :: cmpxchg_ptr (il suo codice asm modifica un campo) e update_barrier_set. Queste funzioni, inoltre, come solo modificare un campo, non aggiornare tutte le linee di caching di un thread.

Mi fraintendono?

    
posta ApeStack 23.03.2017 - 02:21
fonte

1 risposta

0

L'essenza dell'algoritmo usato da ReentrantLock consiste nell'utilizzare un'operazione di confronto e impostazione per garantire che una precedente accessoria del blocco l'abbia rilasciata. La sequenza di operazioni di interesse è:

  • il thread A ha acquisito il blocco, memorizzando un valore che lo identifica nello stato
  • il thread A modifica i dati condivisi
  • il thread A rilascia il blocco, memorizzando un identificatore di stato sbloccato
  • il thread B acquisisce il blocco, ricevendo l'identificatore di stato sbloccato.
  • il thread B accede ai dati condivisi

Ogni operazione all'interno di un singolo thread ha una relazione prima, garantendo la disponibilità di memoria all'interno del thread. Un'operazione di confronto e scambio fornisce anche una relazione di precedenza prima tra la chiamata che imposta il valore e la chiamata che l'ha ricevuta. Pertanto, ogni operazione su questa lista ha una garanzia prima di tutto. Questo è transitivo, quindi possiamo vedere che "il thread A modifica i dati condivisi" accade prima che "il thread B acceda ai dati condivisi", quindi il blocco funziona come previsto.

    
risposta data 23.03.2017 - 13:52
fonte

Leggi altre domande sui tag