Il blocco sincronizzato su System.out.println(number);
richiede il seguente codice?È necessario questo blocco sincronizzato?
import java.util.concurrent.CountDownLatch;
public class Main {
private static final Object LOCK = new Object();
private static long number = 0L;
public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
synchronized (LOCK) { // Is this synchronized block need?
System.out.println(number);
}
}
private static class Worker extends Thread {
private final CountDownLatch doneSignal;
private Worker(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
@Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
}
}
Penso che sia necessario perché c'è la possibilità di leggere il valore memorizzato nella cache.
Ma qualche persona dicono che:
E 'inutile.
Perché quando il thread principale legge la variabile number
, tutto il thread di lavoro ha eseguito l'operazione di scrittura in memoria della variabile number
.
Non importa se i thread sono completati o meno, è importante che il lettore possa vedere il valore numerico attuale. Fortunatamente, coppia countdown() + await() garantisce prima :) :) – qwwdfsad
tutto ciò che conta per 'doneSignal.await()' è che il 'CountDownLatch' raggiunge 0, ciò che succede a 'number' non ha alcuna importanza. Se ha rimosso del tutto il 'CountDownLatch', il thread principale potrebbe effettivamente essere fatto prima che tutti i suoi thread' Worker' vengano eseguiti, a seconda dello scheduler, e stampare sia '0' o qualche altro numero –
Penso ** qwwdfsad ** ' Il punto è che se non ci fosse * prima-prima * tra il codice prima di ogni "countDown()" e il codice dopo "await()", si potrebbe ancora vedere un valore inferiore a 10 per "numero". Se per esempio 'await()' ha funzionato controllando un valore che è stato aggiornato con la vecchia semantica 'volatile' (pre-Java 5.0), poteva vedere in modo affidabile che tutti i thread hanno finito, ma non poteva vedere in modo affidabile l'ultimo valore di 'number'. –