Jika saya menyinkronkan dua metode pada kelas yang sama, dapatkah mereka berjalan secara bersamaan pada objek yang sama ? sebagai contoh:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
Saya tahu bahwa saya tidak dapat menjalankan methodA()
dua kali pada objek yang sama di dua utas yang berbeda. hal yang sama di methodB()
.
Tetapi bisakah saya menjalankan methodB()
thread yang berbeda saat methodA()
masih berjalan? (objek yang sama)
obj.methodB()
adalah sinonim untukA.methodB()
saatmethodB()
inistatic
. Karena itu ya, mereka akan memblokir (pada kelas, bukan objek, monitor)..class
objek. Jadi kalau sudahclass A {static synchronized void m() {} }
. Dan kemudian satu utas menyebutnyanew A().m()
memperoleh kunci padanew A()
objek. Jika kemudian thread lain memanggilA.m()
itu memasuki METODE NO PROBLEM karena apa yang tampak adalah kunci padaA.class
objek sementara NO THREADS memiliki semacam ini kunci . Jadi meskipun Anda menyatakan metodesynchronized
itu sebenarnya diakses oleh dua utas yang berbeda PADA SAAT YANG SAMA . Jadi: jangan pernah menggunakan referensi objek untuk memanggil metode statisDalam contoh methodA dan methodB adalah metode instance (sebagai lawan dari metode statis). Menempatkan
synchronized
metode instance berarti bahwa utas harus mendapatkan kunci ("kunci intrinsik") pada objek contoh di mana metode dipanggil sebelum utas dapat mulai mengeksekusi kode apa pun dalam metode itu.Jika Anda memiliki dua metode instance berbeda yang ditandai tersinkronisasi dan utas berbeda memanggil metode-metode tersebut secara bersamaan pada objek yang sama, utas tersebut akan bersaing untuk kunci yang sama. Setelah satu utas mendapatkan kunci, semua utas lainnya akan ditutup dari semua metode instance yang disinkronkan pada objek itu.
Agar kedua metode dapat berjalan secara bersamaan, mereka harus menggunakan kunci yang berbeda, seperti ini:
di mana sintaksis blok yang disinkronkan memungkinkan menentukan objek tertentu yang perlu dijalankan utas pelaksana untuk mendapatkan kunci intrinsik agar dapat memasuki blok.
Yang penting untuk dipahami adalah bahwa meskipun kami menempatkan kata kunci "tersinkronisasi" pada metode individual, konsep intinya adalah kunci intrinsik di belakang layar.
Berikut adalah cara tutorial Java menjelaskan hubungan:
Tujuan dari penguncian adalah untuk melindungi data yang dibagikan. Anda akan menggunakan kunci terpisah seperti yang ditunjukkan dalam kode contoh di atas hanya jika setiap kunci melindungi anggota data yang berbeda.
sumber
static synchronized
atausynchronized (A.class)
Java Thread mengakuisisi sebuah kunci tingkat objek ketika memasuki sebuah contoh metode java disinkronkan dan mengakuisisi kunci tingkat kelas ketika memasuki statis disinkronisasi metode java.
Dalam kasus Anda, metode (contoh) dari kelas yang sama. Jadi kapan pun sebuah thread masuk ke metode java disinkronkan atau blok itu memperoleh kunci (objek tempat metode dipanggil). Jadi metode lain tidak dapat dipanggil pada saat yang sama pada objek yang sama sampai metode pertama selesai dan kunci (objek) dilepaskan.
sumber
private final Object lock = new object();
dengan disinkronkan untuk memungkinkan hanya satu utas untuk dapat menjalankan salah satu metode? Terima kasihDalam kasus Anda, Anda menyinkronkan dua metode pada instance kelas yang sama. Jadi, kedua metode ini tidak dapat berjalan secara bersamaan pada utas berbeda dari instance yang sama dari kelas A. Tapi mereka bisa pada instance kelas A yang berbeda.
sama dengan:
sumber
private final Object lock = new Object();
dan sekarang digunakanlock
dengan blok disinkronkan dalam dua metode maka akankah pernyataan Anda berlaku? IMO karena Object adalah kelas induk dari semua objek sehingga bahkan jika utas berada pada instance kelas yang berbeda, hanya satu yang dapat mengakses kode di dalam blok yang disinkronkan pada suatu waktu. Terima kasih.Dari tautan dokumentasi oracle
Membuat metode yang disinkronkan memiliki dua efek:
Ini akan menjawab pertanyaan Anda: Pada objek yang sama, Anda tidak dapat memanggil metode tersinkronisasi kedua saat eksekusi metode tersinkronisasi pertama sedang berlangsung.
Lihat halaman dokumentasi ini untuk memahami kunci intrinsik dan perilaku kunci.
sumber
Pikirkan kode Anda seperti di bawah ini:
Jadi, disinkronkan pada level metode berarti disinkronkan (ini). jika ada thread menjalankan metode kelas ini, itu akan mendapatkan kunci sebelum memulai eksekusi dan tahan sampai eksekusi metode selesai.
Memang tidak mungkin!
Oleh karena itu, banyak utas tidak dapat menjalankan sejumlah metode yang disinkronkan pada objek yang sama secara bersamaan.
sumber
Hanya untuk semua kejelasan, Ada kemungkinan bahwa kedua metode disinkronkan statis dan tidak disinkronkan dapat berjalan secara bersamaan atau bersamaan karena seseorang memiliki kunci tingkat objek dan kunci tingkat kelas lainnya.
sumber
The key ide dengan sinkronisasi yang tidak meresap dengan mudah adalah bahwa hal itu hanya akan berpengaruh jika metode yang disebut pada objek yang sama misalnya - itu telah disorot dalam jawaban dan komentar -
Program sampel di bawah ini adalah dengan jelas menunjukkan hal yang sama -
Perhatikan perbedaan dalam output tentang bagaimana akses simultan diizinkan seperti yang diharapkan jika metode dipanggil pada instance objek yang berbeda.
Ouput dengan noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects () berkomentar - outputnya dalam metode urutanA di> methodA Out .. methodB in> methodB Out
dan Ouput dengan sinkronisasiEffectiveAsMethodsCalledOnSameObject () berkomentar - output menunjukkan akses simultan metodeA oleh Thread1 dan Thread0 di bagian yang disorot -
Menambah jumlah utas akan membuatnya semakin terlihat.
sumber
Tidak itu tidak mungkin, jika memungkinkan maka kedua metode dapat memperbarui variabel yang sama secara bersamaan yang dapat dengan mudah merusak data.
sumber
Ya, mereka dapat menjalankan kedua utas secara bersamaan. Jika Anda membuat 2 objek kelas karena setiap objek hanya berisi satu kunci dan setiap metode yang disinkronkan memerlukan kunci. Jadi jika Anda ingin menjalankan secara bersamaan, buat dua objek lalu coba jalankan dengan menggunakan referensi objek tersebut.
sumber
Anda menyinkronkannya pada objek bukan pada kelas. Jadi mereka tidak bisa berjalan secara bersamaan pada objek yang sama
sumber
Dua Thread berbeda yang mengeksekusi metode yang disinkronkan umum pada objek tunggal, karena objeknya sama, ketika satu thread menggunakannya dengan metode yang disinkronkan, itu harus memvariasikan kunci, jika kunci diaktifkan, utas ini akan menunggu status, jika kunci dinonaktifkan maka ia dapat mengakses objek, sementara itu akan mengaksesnya akan mengaktifkan kunci dan akan melepaskan kunci hanya ketika eksekusi selesai. ketika utas lainnya tiba, itu akan memvariasikan kunci, karena diaktifkan itu akan menunggu sampai utas pertama menyelesaikan eksekusi dan melepaskan kunci yang diletakkan pada objek, setelah kunci dilepaskan utas kedua akan mendapatkan akses ke objek dan itu akan mengaktifkan kunci sampai pelaksanaannya. jadi eksekusi tidak akan bersamaan, kedua utas akan mengeksekusi satu per satu,
sumber