ich mit @ Kumar Antwort zustimmen.
Volatile ist nicht ausreichend - es hat einige Auswirkungen auf die Speicherordnung, aber nicht Atomizität von ++.
Die wirklich schwierige Sache über Multithread-Programmierung ist, dass Probleme nicht in einer angemessenen Menge von Tests angezeigt werden können. Ich habe ein Programm geschrieben, um das Problem zu demonstrieren, aber es hat Threads, die nur Zähler inkrementieren. Trotzdem liegen die Zählungen innerhalb von etwa 1% der richtigen Antwort. In einem realen Programm, in dem die Threads andere Aufgaben zu erledigen haben, kann es eine sehr geringe Wahrscheinlichkeit geben, dass zwei Threads das ++ nahe genug machen, um gleichzeitig das Problem zu zeigen. Die Multi-Thread-Korrektheit kann nicht getestet werden, sie muss entworfen werden.
Dieses Programm führt die gleiche Zählaufgabe mit einem einfachen statischen int, einem flüchtigen int und einem AtomicInteger aus. Nur der AtomicInteger bekommt immer die richtige Antwort. Eine typische Ausgabe auf einem Multi-Prozessor mit 4 Dual-Gewindekerne ist:
count: 1981788 volatileCount: 1982139 atomicCount: 2000000 Expected count: 2000000
Hier ist der Quellcode:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
private static int COUNTS_PER_THREAD = 1000000;
private static int THREADS = 2;
private static int count = 0;
private static volatile int volatileCount = 0;
private static AtomicInteger atomicCount = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
List<Thread> threads = new ArrayList<Thread>(THREADS);
for (int i = 0; i < THREADS; i++) {
threads.add(new Thread(new Counter()));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
System.out.println("count: " + count + " volatileCount: " + volatileCount + " atomicCount: "
+ atomicCount + " Expected count: "
+ (THREADS * COUNTS_PER_THREAD));
}
private static class Counter implements Runnable {
@Override
public void run() {
for (int i = 0; i < COUNTS_PER_THREAD; i++) {
count++;
volatileCount++;
atomicCount.incrementAndGet();
}
}
}
}
Sie haben gleichzeitige Zugriffe auf ein 'int' sich zu schützen. Aber "AtomicInteger" ist threadsicher konstruiert. – reprogrammer
'static' hat nichts mit Multithreading zu tun. –
Nach meinem Verständnis verwenden wir in Multithread-Umgebungen flüchtige Variablen anstelle von statischen Variablen. – Vishal