Próbowałem odciąć rywalizację o wątki w moim kodzie, zastępując niektóre bloki synchronized
za pomocą AtomicBoolean
.AtomicBoolean vs zsynchronizowany blok
Oto przykład z synchronized
:
public void toggleCondition() {
synchronized (this.mutex) {
if (this.toggled) {
return;
}
this.toggled = true;
// do other stuff
}
}
i alternatywa z AtomicBoolean
:
public void toggleCondition() {
if (!this.condition.getAndSet(true)) {
// do other stuff
}
}
Wykorzystując własności CAS AtomicBoolean
„s powinien być sposób szybciej niż opierając się na synchronizacji więc wpadłem little micro-benchmark.
Dla 10 równoczesnych wątków i 1000000 iteracji, AtomicBoolean
pojawia się tylko nieznacznie szybciej niż blok synchronized
.
Średni czas (na gwint) spędził na toggleCondition() z AtomicBoolean: 0,0338
Średni czas (na gwint) spędził na toggleCondition() z zsynchronizowanych: 0,0357
wiem mikro odniesienia są warte co są warte, ale czy różnica nie powinna być większa?
Być może na początku nie było wiele sprzeczności w oryginalnym kodzie. Co skłoniło cię do myślenia, że trzeba zoptymalizować? –
Uruchamianie testów wydajności w bibliotece, którą napisałem. Miałem domyślną implementację przy użyciu zsynchronizowanych bloków i ręcznej synchronizacji wait()/notify(). Następnie wypróbowałem inną wersję, używając tylko java.util.concurrent i otrzymałem najgorsze wyniki. Oto klasy: http://github.com/brunodecarvalho/hotpotato/blob/master/src/main/java/org/factor45/hotpotato/request/ConcurrentHttpRequestFuture.java i http://github.com/brunodecarvalho/hotpotato /blob/master/src/main/java/org/factor45/hotpotato/request/DefaultHttpRequestFuture.java – biasedbit
Zdałem sobie sprawę po kolejnym mikro-benchmarku (tak, wiem, że mikro benchmarki są nieco wadliwe ...), że problem polegał faktycznie na użyciu CountDownLatch przez wait()/notify(). Poza tym, że podejście AtomicBoolean nie było całkowicie bezpieczne, więc rzuciłem to. – biasedbit