Jawaban:
Ketika beberapa utas perlu memeriksa dan mengubah boolean. Sebagai contoh:
if (!initialized) {
initialize();
initialized = true;
}
Ini bukan thread-safe. Anda dapat memperbaikinya dengan menggunakan AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
kapan initialize()
belum selesai. Jadi, ini hanya berfungsi jika utas lainnya tidak peduli penyelesaiannya initialize()
.
initialized
hanya digunakan untuk memastikan bahwa satu dan hanya satu utas akan memanggil initialize()
metode. Jelas initialized
benar bukan berarti inisialisasi telah selesai dalam kasus ini, jadi mungkin istilah yang sedikit berbeda akan lebih baik di sini. Sekali lagi, itu tergantung pada apa yang digunakan untuk itu.
volatile boolean
akan sama dengan AtomicBoolean
?
synchronized
blok, dalam hal ini Anda tidak perlu lagi AtomicBoolean
, hanya a volatile boolean
. ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
akan memastikan bahwa hanya satu utas panggilan initialize
, dan bahwa semua utas lainnya menunggu untuk melakukannya, asalkan initialized
ditandai volatile
.)
Ini adalah catatan (dari buku Brian Goetz ) yang saya buat, yang mungkin bisa membantu Anda
Kelas AtomicXXX
menyediakan implementasi Bandingkan-dan-Tukar Non-pemblokiran
Mengambil keuntungan dari dukungan yang diberikan oleh perangkat keras (instruksi CMPXCHG pada Intel) Ketika banyak utas berjalan melalui kode Anda yang menggunakan API konkurensi atom ini, mereka akan berskala jauh lebih baik daripada kode yang menggunakan monitor / sinkronisasi tingkat objek. Karena, mekanisme sinkronisasi Java membuat kode menunggu, ketika ada banyak utas yang berjalan melalui bagian-bagian penting Anda, banyak waktu CPU dihabiskan untuk mengelola mekanisme sinkronisasi itu sendiri (menunggu, memberi tahu, dll.). Karena API baru menggunakan konstruksi tingkat perangkat keras (variabel atom) dan menunggu dan mengunci algoritma gratis untuk menerapkan keamanan ulir, lebih banyak waktu CPU dihabiskan untuk "melakukan hal-hal" daripada mengelola sinkronisasi.
tidak hanya menawarkan throughput yang lebih baik, tetapi mereka juga memberikan perlawanan yang lebih besar terhadap masalah kehidupan seperti kebuntuan dan inversi prioritas.
Ada dua alasan utama mengapa Anda dapat menggunakan boolean atom. Pertama bisa berubah, Anda bisa meneruskannya sebagai referensi dan mengubah nilai yang terkait dengan boolean itu sendiri, misalnya.
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
dan di kelas someObject
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
Lebih penting lagi, utasnya aman dan dapat menunjukkan kepada pengembang yang menjaga kelas, bahwa variabel ini diharapkan akan dimodifikasi dan dibaca dari beberapa utas. Jika Anda tidak menggunakan AtomicBoolean, Anda harus menyinkronkan variabel boolean yang Anda gunakan dengan mendeklarasikannya volatil atau menyinkronkan sekitar bidang baca dan tulis bidang.
The AtomicBoolean
kelas memberi Anda nilai boolean yang Anda dapat memperbarui atom. Gunakan ketika Anda memiliki banyak utas yang mengakses variabel boolean.
The gambaran paket java.util.concurrent.atomic memberikan gambaran tingkat tinggi baik dari apa kelas dalam paket ini dilakukan dan kapan menggunakannya. Saya juga merekomendasikan buku Java Concurrency in Practice oleh Brian Goetz.
Kutipan dari deskripsi paket
Paket deskripsi java.util.concurrent.atomic: Toolkit kecil dari kelas yang mendukung pemrograman bebas-penguncian bebas-kunci pada variabel tunggal. [...]
Spesifikasi dari metode ini memungkinkan implementasi untuk menggunakan instruksi atom tingkat mesin yang efisien yang tersedia pada prosesor kontemporer. [...]
Contoh kelas AtomicBoolean, AtomicInteger, AtomicLong, dan AtomicReference masing-masing memberikan akses dan pembaruan ke satu variabel dari jenis yang sesuai. [...]
Efek memori untuk akses dan pembaruan atom umumnya mengikuti aturan untuk volatil:
- dapatkan memiliki efek memori dari membaca variabel volatile.
- set memiliki efek memori menulis (menugaskan) variabel yang mudah menguap.
- lemahCompareAndSet secara atom membaca dan kondisional menulis variabel, diperintahkan sehubungan dengan operasi memori lain pada variabel itu, tetapi sebaliknya bertindak sebagai operasi memori non-volatil biasa.
- compareAndSet dan semua operasi baca-dan-perbarui lainnya seperti getAndIncrement memiliki efek memori dari membaca dan menulis variabel volatil.
volatile boolean
vsAtomicBoolean
: stackoverflow.com/questions/3786825/…