Blok Tersinkronisasi Java untuk .class

Jawaban:

144

Cuplikan synchronized(X.class)menggunakan instance kelas sebagai monitor. Karena hanya ada satu instance kelas (objek yang mewakili metadata kelas pada waktu proses), satu utas dapat berada di blok ini.

Dengan synchronized(this)blok tersebut dijaga oleh instance. Untuk setiap contoh, hanya satu utas yang dapat memasuki blok.

synchronized(X.class)digunakan untuk memastikan bahwa hanya ada satu Thread di blok. synchronized(this)memastikan bahwa hanya ada satu utas per instance. Jika ini membuat kode sebenarnya di blok thread-aman tergantung pada implementasi. Jika status mutasi saja dari instance synchronized(this)sudah cukup.

Thomas Jung
sumber
6
"sebanyak benang dapat memasuki blok karena ada contoh" menyiratkan bahwa bentuk kedua bertindak sebagai semaphore yang tidak benar. Anda harus mengatakan sesuatu seperti: "disinkronkan (ini) memastikan bahwa hanya satu utas yang dapat memasuki blok untuk instance kelas tertentu".
liwp
Diperbaiki. Saya bermaksud mengatakan itu.
Thomas Jung
2
apa contoh kelas vs contoh?
Weishi Zeng
Jadi, jika Anda memiliki metode statis dan kami tidak ingin menyinkronkan semua tubuhnya, maka yang kami sinkronkan (ini) tidak baik, malah yang disinkronkan (kelas Foo.class) sudah sesuai. Apakah itu benar?
krupal.agile
84

Untuk menambah jawaban lain:

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

setara dengan

static synchronized void myMethod() {
  //code
}

dan

void myMethod() {
  synchronized(this) {
    //code
  }
}

setara dengan

synchronized void myMethod() {
  //code
}
Jorn
sumber
12
Saya membutuhkan pembacaan kedua untuk mengetahui bahwa dua contoh pertama memiliki kata kunci "statis". Hanya menunjukkan hal itu kepada orang lain yang mungkin telah melihat ini dan melewatkannya. Tanpa kata kunci statis, dua contoh pertama tidak akan sama.
kurtzbot
1
Contoh-contoh itu TIDAK setara! Metode yang disinkronkan "disinkronkan" sebagai lubang ketika utas mencoba memanggil metode. Blok di sisi lain, dapat memiliki kode di atas dan di bawahnya, yang dapat dieksekusi dari banyak utas. Mereka hanya melakukan sinkronisasi di dalam blok! Itu tidak sama!
JacksOnF1re
public static Singleton getInstance () {jika (instance == null) {disinkronkan (Singleton.class) {instance = new Singleton (); }} contoh kembali; }
JacksOnF1re
2
Seluruh titik adalah bahwa ada adalah tidak ada kode di luar synchronizedblok. Itu membuat mereka setara. Jika Anda mengubah satu contoh, mereka memang tidak lagi sama.
Jorn
23

Tidak, yang pertama akan mengetahui definisi kelas dari MyClass, tidak semua instance-nya. Namun, jika digunakan dalam sebuah instance, ini akan secara efektif memblokir semua instance lainnya, karena mereka berbagi definisi kelas tunggal.

Yang kedua akan mendapatkan kunci pada instance saat ini saja.

Mengenai apakah ini membuat objek thread Anda aman, itu adalah pertanyaan yang jauh lebih kompleks - kami perlu melihat kode Anda!

David M
sumber
1
ya, MyClass.class dapat berupa variabel statis apa saja dan memiliki efek yang sama.
pstanton
0

Ya, tentu saja.

Saya bertanya-tanya tentang pertanyaan ini selama beberapa hari untuk diri saya sendiri (sebenarnya di kotlin). Saya akhirnya menemukan penjelasan yang bagus dan ingin membagikannya:

Kunci tingkat kelas mencegah beberapa utas masuk dalam blok tersinkronisasi di salah satu dari semua contoh kelas yang tersedia pada waktu proses. Ini berarti jika dalam runtime ada 100 instance DemoClass, maka hanya satu thread yang dapat mengeksekusi demoMethod () di salah satu instance dalam satu waktu, dan semua instance lainnya akan dikunci untuk thread lain.

Penguncian tingkat kelas harus selalu dilakukan untuk membuat utas data statis aman. Seperti yang kita ketahui bahwa kata kunci statis mengasosiasikan data metode ke tingkat kelas, jadi gunakan penguncian pada bidang statis atau metode untuk membuatnya di tingkat kelas.

Baca lebih lanjut: https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/

vitalii
sumber