Saya mencoba memahami apa yang membuat kunci dalam konkurensi sangat penting jika seseorang dapat menggunakannya synchronized (this)
. Dalam kode dummy di bawah ini, saya dapat melakukan salah satu dari ini:
- menyinkronkan seluruh metode atau menyinkronkan area rentan (
synchronized(this){...}
) - ATAU kunci area kode rentan dengan ReentrantLock.
Kode:
private final ReentrantLock lock = new ReentrantLock();
private static List<Integer> ints;
public Integer getResult(String name) {
.
.
.
lock.lock();
try {
if (ints.size()==3) {
ints=null;
return -9;
}
for (int x=0; x<ints.size(); x++) {
System.out.println("["+name+"] "+x+"/"+ints.size()+". values >>>>"+ints.get(x));
}
} finally {
lock.unlock();
}
return random;
}
synchronized(this){synchronized(this){//some code}}
tidak akan menyebabkan kunci mati. Untuk kunci intrinsik jika mereka mendapatkan monitor pada sumber daya dan jika mereka menginginkannya lagi mereka bisa mendapatkannya tanpa kunci mati.Jawaban:
Sebuah ReentrantLock adalah tidak terstruktur , tidak seperti
synchronized
konstruksi - yaitu Anda tidak perlu menggunakan struktur blok untuk mengunci dan bahkan dapat memegang kunci di seluruh metode. Sebuah contoh:Aliran seperti itu tidak mungkin untuk diwakili melalui monitor tunggal dalam suatu
synchronized
konstruksi.Selain itu,
ReentrantLock
mendukung polling kunci dan kunci interruptible menunggu yang mendukung time-out .ReentrantLock
juga memiliki dukungan untuk kebijakan keadilan yang dapat dikonfigurasi , memungkinkan penjadwalan thread yang lebih fleksibel.ReentrantLock
mungkin juga lebih skalabel , berkinerja jauh lebih baik di bawah pertengkaran yang lebih tinggi. Anda dapat membaca lebih lanjut tentang ini di sini .Namun klaim ini telah diperdebatkan; lihat komentar berikut:
Kapan sebaiknya Anda gunakan
ReentrantLock
s? Menurut artikel developerWorks itu ...sumber
ReentrantLockPseudoRandom
kode di tautan Lycog menggunakan kunci baru yang tidak dikunci setiap pemanggilansetSeed
dannext
ReentrantReadWriteLock
adalah kunci khusus sedangkansynchronized(this)
kunci tujuan umum. Mereka serupa tetapi tidak persis sama.Anda benar bahwa Anda bisa menggunakan
synchronized(this)
bukannyaReentrantReadWriteLock
tetapi sebaliknya tidak selalu benar.Jika Anda ingin lebih memahami apa yang membuat
ReentrantReadWriteLock
khusus mencari informasi tentang sinkronisasi utas produsen-konsumen.Secara umum Anda dapat mengingat bahwa sinkronisasi seluruh metode dan sinkronisasi tujuan umum (menggunakan
synchronized
kata kunci) dapat digunakan di sebagian besar aplikasi tanpa terlalu memikirkan semantik sinkronisasi tetapi jika Anda perlu memeras kinerja dari kode Anda, Anda mungkin perlu mengeksplorasi mekanisme sinkronisasi dengan tujuan lebih baik, atau tujuan khusus lainnya.Ngomong-ngomong, menggunakan
synchronized(this)
- dan secara umum mengunci menggunakan instance kelas publik - dapat menjadi masalah karena membuka kode Anda ke kunci-mati potensial karena orang lain yang tidak sengaja mungkin mencoba untuk mengunci objek Anda di tempat lain di dalam program.sumber
public class MyLock { private final Object protectedLongLockingMonitor = new Object(); private long protectedLong = 0L; public void incrementProtectedLong() { synchronized(protectedLongLockingMonitor) { protectedLong++; } } }
Dari halaman dokumentasi oracle tentang ReentrantLock :
Sebuah ReentrantLock dimiliki oleh benang yang terakhir berhasil mengunci, tetapi belum unlocking. Kunci pemanggilan utas akan kembali, berhasil memperoleh kunci, saat kuncinya tidak dimiliki oleh utas lainnya. Metode ini akan segera kembali jika utas saat ini sudah memiliki kunci.
Konstruktor untuk kelas ini menerima parameter keadilan opsional . Ketika disetel benar, di bawah pertentangan, kunci mendukung pemberian akses ke utas terlama . Kalau tidak, kunci ini tidak menjamin urutan akses tertentu.
Fitur kunci ReentrantLock sesuai artikel ini
Kamu bisa memakai ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock untuk mendapatkan kontrol lebih lanjut pada penguncian granular pada operasi baca dan tulis.
Lihat artikel ini oleh Benjamen tentang penggunaan berbagai jenis ReentrantLocks
sumber
Anda dapat menggunakan kunci reentrant dengan kebijakan keadilan atau batas waktu untuk menghindari kelaparan utas. Anda dapat menerapkan kebijakan kewajaran utas. itu akan membantu menghindari utas menunggu selamanya untuk mendapatkan sumber daya Anda.
"Kebijakan keadilan" mengambil utas yang dapat dijalankan berikutnya untuk dijalankan. Ini didasarkan pada prioritas, waktu sejak dijalankan terakhir, bla bla
juga, Sinkronisasi dapat memblokir tanpa batas jika tidak dapat keluar dari blok. Reentrantlock dapat memiliki batas waktu yang ditetapkan.
sumber
Kunci yang disinkronkan tidak menawarkan mekanisme antrian menunggu di mana setelah eksekusi satu utas, setiap utas yang berjalan secara paralel dapat memperoleh kunci. Karena itu utas yang ada dalam sistem dan berjalan untuk periode waktu yang lebih lama tidak pernah mendapat kesempatan untuk mengakses sumber daya bersama sehingga mengarah ke kelaparan.
Kunci reentrant sangat fleksibel dan memiliki kebijakan keadilan di mana jika utas menunggu untuk waktu yang lebih lama dan setelah selesainya utas yang saat ini dijalankan, kami dapat memastikan bahwa utas yang lebih lama mendapat kesempatan untuk mengakses sumber daya bersama dengan menurunnya throughput sistem dan membuatnya lebih memakan waktu.
sumber
Mari kita asumsikan kode ini berjalan di utas:
Karena utas memiliki kunci, maka akan memungkinkan beberapa panggilan untuk mengunci (), sehingga memasukkan kembali kunci. Ini dapat dicapai dengan jumlah referensi sehingga tidak harus mendapatkan kunci lagi.
sumber
Satu hal yang perlu diingat adalah:
Nama ' ReentrantLock ' memberikan pesan yang salah tentang mekanisme penguncian lain bahwa mereka tidak masuk kembali. Ini tidak benar.Kunci yang diperoleh melalui 'disinkronkan' juga masuk kembali di Jawa.
Perbedaan utama adalah bahwa 'disinkronkan' menggunakan kunci intrinsik (kunci yang dimiliki setiap Objek) sedangkan Kunci API tidak.
sumber
Saya pikir metode wait / notify / notifyAll tidak termasuk dalam kelas Object karena mencemari semua objek dengan metode yang jarang digunakan. Mereka jauh lebih masuk akal pada kelas Lock khusus. Jadi dari sudut pandang ini, mungkin lebih baik menggunakan alat yang secara eksplisit dirancang untuk pekerjaan yang ada - yaitu ReentrantLock.
sumber