Cześć, po przeczytaniu "Java concurrency in Practice" bawię kilkoma rzeczami, które miałem potrzebę samemu sprawdzić eksperymentalnie.
Przede wszystkim najmocniej analizowałem safe publication podczas czytania.
Wtajemniczeni kojarzą być może taki obiekt:
public class Holder {
private int n;
public Holder(int n) {
this.n = n;
}
public void assertSanity() {
if (n != n)
throw new AssertionError("This statement is false.");
}
}
Napisałem sobie jakiegoś callera:
public class Main {
private Holder holder;
void execute() throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(100);
final Thread thread = new Thread(() -> holder = new Holder(1000));
// thread.start(); // A
// thread.join(); // A+B
holder = new Holder(1000); // C
for (int i = 0; i < 1000; ++i) {
executorService.execute(() -> holder.assertSanity());
}
executorService.shutdown();
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
}
I teraz tak ...
A - mamy unsafe publication, bo przetestowałem i czasami leci NPE na holderze jak executor w innych wątkach odpala na nim assertSanity
. Nigdy jednak nie udało mi się dostać wyjątku AssertionError
czyli, że referencja do holdera była, ale stan był niespójny. Być może po prostu taka sytuacja na nowych javach ma miejsce wyjątkowo rzadko?
A + B - tutaj nie udało mi się wywalić niczego, zawsze działa. Dlaczego? Przecież wątek callera to inny wątek niż te w executorze i mimo, że czekam aż się ten wątek inicjujący holdera wykona to one zawsze go widzą? To znowu efekt super nowych JDK?
C - tutaj podobnie jak w A+B, nie udało mi się wywalić i pewnie sprawa jest podobna jak w pkt poprzednim?
Pytanie bonus ...
Skoro konstruktory nie są synchronizowane to jeśli tworzymy obiekt, który będzie zaraz czytany przez wiele innych wątków to czy referencje nie powinna być zawsze final
lub volatile
? Dodatkowo jeśli ten obiekt jest mutowalny to czy w konstruktorze nie trzeba założyć locka? Albo zrobić ewentualnie metodę fabrykującą jako synchronized
?