java.util.concurrent
API menyediakan kelas yang disebut Lock
, yang pada dasarnya akan membuat serial kontrol untuk mengakses sumber daya kritis. Ini memberikan metode seperti park()
dan unpark()
.
Kita bisa melakukan hal serupa jika kita dapat menggunakan synchronized
kata kunci dan menggunakan wait()
dan notify() notifyAll()
metode.
Saya bertanya-tanya mana yang lebih baik dalam praktiknya dan mengapa?
Jawaban:
Jika Anda hanya mengunci objek, saya lebih suka menggunakan
synchronized
Contoh:
Anda harus secara eksplisit melakukannya di
try{} finally{}
mana - mana.Sedangkan dengan disinkronkan, sangat jelas dan tidak mungkin salah:
Yang mengatakan,
Lock
s mungkin lebih berguna untuk hal-hal yang lebih rumit di mana Anda tidak dapat memperoleh dan melepaskan sedemikian bersih. Jujur saya lebih suka untuk menghindari menggunakan telanjangLock
di tempat pertama, dan hanya pergi dengan kontrol konkurensi yang lebih canggih sepertiCyclicBarrier
atauLinkedBlockingQueue
,, jika mereka memenuhi kebutuhan Anda.Saya tidak pernah punya alasan untuk menggunakan
wait()
ataunotify()
tetapi mungkin ada beberapa yang bagus.sumber
std::lock_guard
Saya telah menemukan itu
Lock
danCondition
(danconcurrent
kelas baru lainnya ) hanyalah lebih banyak alat untuk kotak alat. Saya dapat melakukan hampir semua yang saya butuhkan dengan palu cakar saya yang lama (synchronized
kata kunci), tetapi rasanya canggung untuk digunakan dalam beberapa situasi. Beberapa dari situasi yang canggung itu menjadi jauh lebih mudah setelah saya menambahkan lebih banyak alat ke dalam kotak alat saya: palu karet, palu ball-peen, prybar, dan beberapa pukulan paku. Namun , palu cakar saya yang lama masih melihat penggunaannya.Saya tidak berpikir satu benar-benar "lebih baik" dari yang lain, tetapi masing-masing lebih cocok untuk masalah yang berbeda. Singkatnya, model sederhana dan sifat berorientasi lingkup
synchronized
membantu melindungi saya dari bug dalam kode saya, tetapi keuntungan yang sama kadang-kadang menjadi hambatan dalam skenario yang lebih kompleks. Ini skenario yang lebih kompleks bahwa paket bersamaan dibuat untuk membantu mengatasi. Tetapi menggunakan konstruksi tingkat yang lebih tinggi ini memerlukan manajemen kode yang lebih eksplisit dan hati-hati.===
Saya pikir JavaDoc melakukan pekerjaan yang baik untuk menggambarkan perbedaan antara
Lock
dansynchronized
(penekanannya adalah milik saya):sumber
Anda dapat mencapai segala sesuatu utilitas di java.util.concurrent lakukan dengan primitif tingkat rendah seperti
synchronized
,volatile
atau menunggu / memberitahukanNamun, konkurensi itu rumit, dan kebanyakan orang mendapatkan setidaknya sebagiannya salah, membuat kode mereka salah atau tidak efisien (atau keduanya).
API bersamaan menyediakan pendekatan tingkat yang lebih tinggi, yang lebih mudah (dan karena itu lebih aman) untuk digunakan. Singkatnya, Anda tidak perlu menggunakan
synchronized, volatile, wait, notify
secara langsung lagi.Kelas Lock itu sendiri ada di sisi level bawah kotak alat ini, Anda bahkan mungkin tidak perlu menggunakannya secara langsung (Anda dapat menggunakan
Queues
dan Semaphore dan sebagainya, dll, sebagian besar waktu).sumber
java.util.concurrent
lebih mudah [secara umum] daripada fitur bahasa (synchronized
, dll ...). Ketika Anda menggunakanjava.util.concurrent
Anda harus membiasakan menyelesaikanlock.lock(); try { ... } finally { lock.unlock() }
sebelum menulis kode sedangkan dengansynchronized
Anda pada dasarnya baik-baik saja dari awal. Atas dasar ini saja saya akan mengatakansynchronized
lebih mudah (mengingat Anda ingin perilakunya) daripadajava.util.concurrent.locks.Lock
. par 4Ada 4 faktor utama mengapa Anda ingin menggunakan
synchronized
ataujava.util.concurrent.Lock
.Catatan: Penguncian yang disinkronkan adalah yang saya maksud ketika saya mengatakan penguncian intrinsik.
Ketika Java 5 keluar dengan ReentrantLocks, mereka terbukti memiliki perbedaan throughput perbedaan yang cukup dengan penguncian intrinsik. Jika Anda mencari mekanisme penguncian yang lebih cepat dan sedang menjalankan 1.5 pertimbangkan jucReentrantLock. Penguncian intrinsik Java 6 sekarang dapat dibandingkan.
jucLock memiliki mekanisme penguncian yang berbeda. Lock interruptable - upaya untuk mengunci sampai utas pengunci terputus; kunci waktunya - upaya untuk mengunci selama waktu tertentu dan menyerah jika Anda tidak berhasil; tryLock - upaya untuk mengunci, jika ada utas lain yang menahan kunci menyerah. Ini semua disertakan selain dari kunci sederhana. Penguncian intrinsik hanya menawarkan penguncian sederhana
sumber
Saya ingin menambahkan beberapa hal lagi di atas jawaban Bert F.
Locks
mendukung berbagai metode untuk kontrol kunci berbutir halus, yang lebih ekspresif daripada monitor implisit (synchronized
kunci)Keuntungan dari Sinkronisasi Terkunci dari halaman dokumentasi
Penggunaan metode atau pernyataan yang disinkronkan memberikan akses ke kunci monitor implisit yang terkait dengan setiap objek, tetapi memaksa semua akuisisi dan pelepasan kunci terjadi dengan cara terstruktur-blok
Implementasi kunci memberikan fungsionalitas tambahan atas penggunaan metode dan pernyataan yang disinkronkan dengan memberikan upaya non-pemblokiran untuk memperoleh
lock (tryLock())
, upaya untuk mendapatkan kunci yang dapat diinterupsi (lockInterruptibly()
, dan upaya untuk mendapatkan kunci yang bisatimeout (tryLock(long, TimeUnit))
.Kelas kunci juga dapat memberikan perilaku dan semantik yang sangat berbeda dari kunci monitor implisit, seperti pemesanan terjamin, penggunaan non-reentran, atau deteksi kebuntuan
ReentrantLock : Dalam istilah sederhana sesuai pemahaman saya,
ReentrantLock
memungkinkan objek masuk kembali dari satu bagian kritis ke bagian kritis lainnya. Karena Anda sudah memiliki kunci untuk memasuki satu bagian penting, Anda dapat bagian penting lainnya pada objek yang sama dengan menggunakan kunci saat ini.ReentrantLock
fitur utama sesuai artikel iniAnda dapat menggunakan
ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
untuk mendapatkan kontrol lebih lanjut pada penguncian granular pada operasi baca dan tulis.Terlepas dari tiga ReentrantLocks ini, java 8 menyediakan satu lagi Kunci
StampedLock:
Anda dapat menggunakan perangko ini untuk melepaskan kunci atau untuk memeriksa apakah kunci masih valid. Selain itu kunci yang dicap mendukung mode kunci lain yang disebut penguncian optimis.
Lihat artikel ini tentang penggunaan berbagai jenis
ReentrantLock
danStampedLock
kunci.sumber
Perbedaan utama adalah keadilan, dengan kata lain apakah permintaan ditangani FIFO atau dapatkah ada tongkang? Sinkronisasi tingkat metode memastikan alokasi kunci atau FIFO adil. Menggunakan
atau
tidak menjamin keadilan.
Jika Anda memiliki banyak pertentangan untuk kunci tersebut, Anda dapat dengan mudah menemukan barging di mana permintaan yang lebih baru mendapatkan kunci dan permintaan yang lebih lama macet. Saya telah melihat kasus di mana 200 utas tiba dalam waktu singkat untuk kunci dan yang ke-2 tiba diproses terakhir. Ini ok untuk beberapa aplikasi tetapi untuk yang lain mematikan.
Lihat buku "Java Concurrency In Practice" karya Brian Goetz, bagian 13.3 untuk diskusi lengkap tentang topik ini.
sumber
Buku "Java Concurrency In Practice" karya Brian Goetz, bagian 13.3: "... Seperti ReentrantLock default, penguncian intrinsik tidak memberikan jaminan keadilan deterministik, tetapi jaminan keadilan statistik dari sebagian besar implementasi penguncian cukup baik untuk hampir semua situasi ..."
sumber
Kunci membuat hidup programmer lebih mudah. Berikut adalah beberapa situasi yang dapat dicapai dengan mudah dengan kunci.
Sementara itu, kunci, dan kondisinya dibangun berdasarkan mekanisme tersinkronisasi. Karena itu, tentu saja dapat mencapai fungsi yang sama yang dapat Anda capai menggunakan kunci. Namun, menyelesaikan skenario kompleks dengan disinkronkan dapat membuat hidup Anda sulit dan dapat menyimpang Anda dari memecahkan masalah yang sebenarnya.
sumber
Perbedaan utama antara kunci dan disinkronkan:
sumber
Mengunci dan menyinkronkan blok keduanya memiliki tujuan yang sama tetapi tergantung pada penggunaan. Pertimbangkan bagian di bawah ini
Dalam kasus di atas, jika utas memasuki blok sinkronisasi, blok lainnya juga dikunci. Jika ada beberapa blok sinkronisasi seperti itu pada objek yang sama, semua blok dikunci. Dalam situasi seperti itu, java.util.concurrent.Lock dapat digunakan untuk mencegah penguncian blok yang tidak diinginkan
sumber