class ThreadSafeClass extends Thread
{
private static int count = 0;
public synchronized static void increment()
{
count++;
}
public synchronized void decrement()
{
count--;
}
}
Adakah yang bisa menjelaskan mengapa kelas di atas tidak aman untuk benang?
java
multithreading
thread-safety
das kinder
sumber
sumber
increment
) itu akan menjadi thread aman. Atau jika Anda menggunakan beberapa objek pengunci. Seperti yang saya katakan, saya tidak tahu tentang Java - komentar saya berasal dari pengetahuan C #.synchronized
harus digunakan hanya dalam metode statis. Jadi menurut pendapat saya, bahkan jika Anda menghapusincrement
metode ini, itu masih tidak aman untuk thread karena dua instance (yang hanya menyinkronkan akses melalui instance yang sama) dapat memanggil metode ini secara bersamaan.Jawaban:
Karena
increment
metode inistatic
akan melakukan sinkronisasi pada objek kelas untukThreadSafeClass
. Thedecrement
Metode tidak statis dan akan melakukan sinkronisasi pada contoh digunakan untuk menyebutnya. Yaitu, mereka akan melakukan sinkronisasi pada objek yang berbeda dan dengan demikian dua utas berbeda dapat mengeksekusi metode pada saat yang bersamaan. Karena operasi++
dan--
tidak atomik, kelas tidak aman untuk thread.Selain itu, karena
count
itustatic
, mengubahnya daridecrement
yang merupakan metode instance tersinkronisasi tidak aman karena dapat dipanggil pada instance yang berbeda dan dimodifikasicount
secara bersamaan.sumber
count
adastatic
, memiliki metode instancedecrement()
yang salah, meskipun tidak adastatic
increment()
metode, karena dua utas dapat dipanggildecrement()
pada instance berbeda yang memodifikasi penghitung yang sama secara bersamaan.synchronized
blok secara umum (bahkan pada seluruh konten metode) daripada menggunakan pengubah pada metode, yaitusynchronized(this) { ... }
dansynchronized(ThreadSafeClass.class) { ... }
.++
dan--
tidak atom, bahkan padavolatile int
.Synchronized
menangani masalah baca / perbarui / tulis dengan++
/--
, tetapistatic
kata kuncinya adalah, yah, kuncinya di sini. Jawaban yang bagus!synchronized
metode instance. Hanya saja, jangan berharap "disinkronkan" pada metode instance untuk memberikan perlindungan untuk data statis. Satu-satunya masalah di sini adalah apa yang Anda katakan di paragraf pertama Anda: Metode menggunakan kunci yang berbeda dalam upaya untuk melindungi data yang sama, dan tentu saja tidak memberikan perlindungan sama sekali.Anda memiliki dua metode tersinkronisasi, tetapi salah satunya statis dan yang lainnya tidak. Saat mengakses metode tersinkronisasi, berdasarkan jenisnya (statis atau non-statis), objek yang berbeda akan dikunci. Untuk metode statis, kunci akan diletakkan pada objek Kelas, sedangkan untuk blok non-statis, kunci akan diletakkan pada instance kelas yang menjalankan metode tersebut. Karena Anda memiliki dua objek terkunci yang berbeda, Anda dapat memiliki dua utas yang memodifikasi objek yang sama secara bersamaan.
sumber
increment
menjadi statis, sinkronisasi akan dilakukan pada kelas itu sendiri.decrement
karena tidak statis, sinkronisasi akan dilakukan pada instansiasi objek, tetapi itu tidak mengamankan apa pun karenacount
statis.Saya ingin menambahkan itu untuk mendeklarasikan penghitung thread-safe, saya yakin cara paling sederhana adalah menggunakan
AtomicInteger
alih-alih int primitif.Biarkan saya mengarahkan Anda ke
java.util.concurrent.atomic
info-paket.sumber
Jawaban orang lain cukup bagus menjelaskan alasannya. Saya hanya menambahkan sesuatu untuk diringkas
synchronized
:synchronized
aktiffun1
danfun2
disinkronkan pada tingkat objek instance.synchronized
onfun4
disinkronkan pada level objek kelas. Yang berarti:a1.fun1()
pada saat yang sama, panggilan terakhir akan diblokir.a1.fun1()
dan utas 2 panggilana1.fun2()
pada saat bersamaan, panggilan terakhir akan diblokir.a1.fun1()
dan thread 2 panggilana1.fun3()
pada saat yang sama, tidak ada pemblokiran, 2 metode akan dijalankan pada waktu yang sama.A.fun4()
, jika utas lain memanggilA.fun4()
atauA.fun5()
pada saat yang sama, panggilan terakhir akan diblokir karenasynchronized
padafun4
tingkat kelas.A.fun4()
, utas 2 panggilana1.fun1()
pada saat yang sama, tidak ada pemblokiran, 2 metode akan dijalankan pada waktu yang sama.sumber
decrement
mengunci hal lainincrement
agar tidak saling menghalangi untuk berjalan.decrement
pada satu instance berarti mengunci hal yang berbeda dengan memanggildecrement
instance lain, tetapi keduanya memengaruhi hal yang sama.Yang pertama berarti bahwa panggilan yang tumpang tindih
increment
dandecrement
dapat mengakibatkan pembatalan (benar), kenaikan atau penurunan.Yang kedua berarti bahwa dua panggilan yang tumpang tindih ke
decrement
instance yang berbeda dapat mengakibatkan penurunan ganda (benar) atau satu penurunan.sumber
Karena dua metode berbeda, yang satu adalah tingkat instance dan yang lainnya adalah tingkat kelas, jadi Anda perlu mengunci 2 objek yang berbeda untuk menjadikannya ThreadSafe
sumber
Seperti dijelaskan di jawaban lain, kode Anda tidak aman untuk Thread karena metode statis
increment()
mengunci Monitor kelas dan metode non-statisdecrement()
mengunci Monitor objek.Untuk contoh kode ini, ada solusi yang lebih baik tanpa
synchronzed
penggunaan kata kunci. Anda harus menggunakan AtomicInteger untuk mencapai keamanan Thread.Benang aman menggunakan
AtomicInteger
:sumber