====== Потоки и переменные ====== ===== Использование volatile - не безопастно к потокам ===== import static java.lang.System.out; import java.util.Collection; import java.util.LinkedList; public class EntryPoint { private volatile int counter = 0; class ChildThread extends Thread { public void run() { for (int i=0; i<1000; i++) { counter++; } } } public EntryPoint() throws InterruptedException { Collection threads = new LinkedList(); for (int i=0; i<100; i++ ) { Thread th = new ChildThread(); threads.add(th); th.start(); } for (Thread thread : threads) { thread.join(); } out.println("Done!"); out.println(String.format("Now counter == %d", counter)); } public static void main(String []args) throws InterruptedException { var ep = new EntryPoint(); } } java -cp /tmp/WkigqTFpnD EntryPoint Done! Now counter == 97533 ===== Использование Atomic - безопастно к потокам ===== import static java.lang.System.out; import java.util.Collection; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; public class EntryPoint { private AtomicInteger counter = new AtomicInteger(0); class ChildThread extends Thread { public void run() { for (int i=0; i<1000; i++) { counter.addAndGet(1); } } } public EntryPoint() throws InterruptedException { Collection threads = new LinkedList(); for (int i=0; i<100; i++ ) { Thread th = new ChildThread(); threads.add(th); th.start(); } for (Thread thread : threads) { thread.join(); } out.println("Done!"); out.println(String.format("Now counter == %d", counter.get())); } public static void main(String []args) throws InterruptedException { var ep = new EntryPoint(); } } java -cp /tmp/WkigqTFpnD EntryPoint Done! Now counter == 100000 ===== Использование synchronized - безопастно к потокам ===== Интересное замечание, создание простых synchronized функций создают гораздо меньше байткода. import static java.lang.System.out; import java.util.Collection; import java.util.LinkedList; public class EntryPoint { private int counter = 0; private synchronized void increment() { // Синхронизированная функция, меньше байткода this.counter++; } private void increment2() { // Синхронизированный блок synchronized(EntryPoint.class) { counter++; }; } class ChildThread extends Thread { public void run() { for (int i=0; i<1000; i++) { increment2(); // И `increment` и `increment2` создают одинаковый результат } } } public EntryPoint() throws InterruptedException { Collection threads = new LinkedList(); for (int i=0; i<100; i++ ) { Thread th = new ChildThread(); threads.add(th); th.start(); } for (Thread thread : threads) { thread.join(); } out.println("Done!"); out.println(String.format("Now counter == %d", counter)); } public static void main(String []args) throws InterruptedException { var ep = new EntryPoint(); } } java -cp /tmp/WkigqTFpnD EntryPoint Done! Now counter == 100000