Il modello java meomry richiede che i blocchi synchronize
sincronizzati sullo stesso monitor applichino un rendering prima-dopo sulle variabili modificate all'interno di tali blocchi. Esempio:Modello di memoria Java: riordinamento e blocchi simultanei
// in thread A
synchronized(lock)
{
x = true;
}
// in thread B
synchronized(lock)
{
System.out.println(x);
}
In questo caso è garantito che filo B vedrà x==true
finché filo A già passato che synchronized
-block. Ora sono in procinto di riscrivere un sacco di codice per utilizzare i blocchi più flessibili (e detti per essere più veloci) in java.util.concurrent
, in particolare lo ReentrantReadWriteLock
. Così, l'esempio si presenta così:
EDIT: L'esempio è stato rotto, perché ho erroneamente trasformato il codice, come notato da matt b. Fissati come segue:
// in thread A
lock.writeLock().lock();
{
x = true;
}
lock.writeLock().unlock();
// in thread B
lock.readLock().lock();
{
System.out.println(x);
}
lock.readLock().unlock();
Tuttavia, non ho visto alcun suggerimento all'interno della specificazione modello di memoria che tali serrature anche implicano l'ordinamento nessessary. Analizzando l'implementazione sembra basarsi sull'accesso a variabili volatili all'interno di AbstractQueuedSynchronizer
(almeno per l'implementazione del sole). Tuttavia questo non fa parte di alcuna specifica e inoltre l'accesso alle variabili non volatili non è realmente contemplato dalla barriera di memoria data da queste variabili, vero?
Così, qui sono le mie domande:
- E 'lecito ritenere lo stesso ordinamento come con i "vecchi"
synchronized
blocchi? - È documentato da qualche parte?
- L'accesso a qualsiasi variabile volatile è una barriera di memoria per qualsiasi altra variabile?
Saluti, Steffen
-
Commento a Yanamon:
un'occhiata al codice seguente:
// in thread a
x = 1;
synchronized (a) { y = 2; }
z = 3;
// in thread b
System.out.println(x);
synchronized (a) { System.out.println(y); }
System.out.println(z);
Da quello che ho capito, la barriera di memoria fa rispettare il secondo output mostra 2, ma non ha alcun effetto garantito sulle altre variabili ...? Quindi, come può essere paragonato all'accesso a una variabile volatile?
Una nota sul codice che hai aggiunto, il thread b stamperà solo 2 se ottiene il blocco per un thread precedente a ... che è stato un po 'implicito ma volevo solo chiarirlo. Ma per rispondere a questa domanda volatile, si può usare volatile nel modo seguente per rafforzare la visibilità: -------- volatile memoria booleana Barrier = falso; int unguardedValue = 0; // thread a: unguardedValue = 10; memoryBarrier = true; // thread b if (memoriaBarrier) { // unguardedValue è garantito per essere letto come 10; } – Yanamon
Beh, immagino che scrivere codice nei commenti non funzioni davvero bene, ho aggiornato la mia risposta con un esempio – Yanamon