it-swarm-id.com

Apakah int volatile di Java thread-safe?

Apakah volatile int di Java thread-safe? Yaitu, dapatkah itu dibaca dan ditulis dengan aman tanpa mengunci?

49
shawn

Ya, Anda dapat membaca dan menulis dengan aman - tetapi Anda tidak dapat melakukan senyawa apa pun seperti menambahkannya dengan aman, karena itu adalah siklus baca/modifikasi/tulis. Ada juga masalah bagaimana interaksi dengan akses ke variabel lainnya.

Sifat pasti dari volatile terus terang membingungkan (lihat bagian model memori JLS untuk lebih jelasnya ) - Saya akan secara pribadi umumnya menggunakan AtomicInteger sebagai gantinya, sebagai cara sederhana untuk memastikan saya lakukan dengan benar.

63
Jon Skeet

[...] seperti dapat dibaca dan ditulis dengan aman tanpa mengunci?

Ya, membaca akan selalu menghasilkan nilai dari penulisan terakhir, (dan keduanya membaca dan menulis adalah operasi atom).

Baca/tulis volatile memperkenalkan apa yang disebut relasi terjadi-sebelum dalam eksekusi.

Dari Spesifikasi Bahasa Jawa Bab 17: Threads and Locks

Penulisan ke bidang volatil (§8.3.1.4) terjadi sebelum setiap pembacaan berikutnya dari bidang itu.

Dengan kata lain, ketika berhadapan dengan variabel volatil, Anda tidak perlu menyinkronkan secara eksplisit (memperkenalkan hubungan sebelum-kejadian) menggunakan kata kunci synchronized untuk memastikan bahwa utas mendapatkan nilai terbaru yang dituliskan ke variabel.

Seperti yang ditunjukkan oleh Jon Skeet, penggunaan variabel volatil terbatas, dan Anda harus mempertimbangkan penggunaan kelas dari paket Java.util.concurrent secara umum.

6
aioobe

Akses ke volatile int di Java akan aman-utas. Ketika saya mengatakan akses, saya maksud unit operasi di atasnya, seperti volatile_var = 10 atau int temp = volatile_var (pada dasarnya tulis/baca dengan nilai konstan). Kata kunci yang mudah menguap di Jawa memastikan dua hal:

  1. Saat membaca Anda selalu mendapatkan nilai di memori utama. Umumnya untuk keperluan optimasi, JVM menggunakan register atau dalam istilah yang lebih umum memori lokal musuh penyimpanan/variabel akses. Jadi dalam lingkungan multi-threaded, masing-masing thread dapat melihat salinan variabel yang berbeda. Tetapi membuatnya volatile memastikan bahwa menulis ke variabel memerah ke memori utama dan membacanya juga terjadi dari memori utama dan karenanya memastikan bahwa utas melihat pada salinan variabel yang benar.
  2. Akses ke volatile disinkronkan secara otomatis. Jadi JVM memastikan pemesanan sambil membaca/menulis ke variabel.

Namun Jon Skeet menyebutkan dengan benar bahwa dalam operasi non atom (volatile_var = volatile + 1) utas yang berbeda mungkin mendapatkan hasil yang tidak terduga.

2
Saurabh

1) Jika dua utas sama-sama membaca dan menulis ke variabel bersama, maka menggunakan kata kunci yang mudah menguap untuk itu tidak cukup. Anda perlu menggunakan sinkronisasi dalam kasus itu untuk menjamin bahwa pembacaan dan penulisan variabel adalah atom. Membaca atau menulis variabel volatile tidak menghalangi utas membaca atau menulis. Agar ini terjadi, Anda harus menggunakan kata kunci yang disinkronkan di sekitar bagian penting.

2) Sebagai alternatif untuk blok yang disinkronkan, Anda juga dapat menggunakan salah satu dari banyak tipe data atom yang ditemukan dalam paket Java.util.concurrent. Misalnya, AtomicLong atau AtomicReference atau yang lainnya.

Utas aman jika Anda memiliki satu utas penulis dan utas banyak pembaca.

class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}

Catatan: Jika helper tidak dapat diubah maka tidak perlu kata kunci yang mudah menguap. Di sini singleton akan berfungsi dengan baik. 

Dalam kasus penghitung yang sedang ditambahkan oleh banyak utas (operasi penulisan membaca) tidak akan memberikan jawaban yang benar. Kondisi ini juga diilustrasikan oleh kondisi ras.

public class Counter{
private volatile int i;
public int increment(){
i++;
}
}

CATATAN: Volatilitas di sini tidak akan membantu.

0
Rahul Saxena

Jika volatile tidak bergantung pada variabel volatile lain, utasnya aman untuk operasi baca. Dalam kasus penulisan volatile tidak menjamin keamanan utas.

Asumsikan Anda memiliki variabel i yang volatil dan nilainya tergantung pada variabel volatil lainnya, katakanlah j. Sekarang variabel akses Thread-1 j dan menambahkannya dan akan memperbaruinya di memori utama dari cache CPU. Dalam hal Thread-2 membaca
variabel i sebelum Thread-1 benar-benar dapat memperbarui j di memori utama. Nilai i akan sesuai dengan nilai lama j yang tidak benar. Ini juga disebut Dirty read.

0
Ajay Verma

Tidak selalu. 

Ini bukan utas aman jika banyak utas sedang menulis dan membaca variabel. Utas aman jika Anda memiliki satu utas penulis dan utas banyak pembaca. 

Jika Anda mencari Thread dengan aman, gunakan AtomicXXX kelas

Toolkit kecil kelas yang mendukung pemrograman aman-thread-bebas pada variabel tunggal. 

Pada dasarnya, kelas-kelas dalam paket ini memperluas gagasan nilai volatil, bidang, dan elemen array ke kelas yang juga menyediakan operasi pembaruan kondisional atom dari bentuk:

boolean compareAndSet(expectedValue, updateValue);

Lihat @untuk menjawab di posting di bawah ini:

Volatile boolean vs AtomicBoolean

0
Ravindra babu