====== Потоки и переменные ======
===== Использование 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