Содержание

Потоки и переменные

Использование 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<Thread> threads = new LinkedList<Thread>();
        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<Thread> threads = new LinkedList<Thread>();
        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<Thread> threads = new LinkedList<Thread>();
        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