Sebelum Java 5.0, satu -satunya mekanisme yang dapat digunakan untuk mengoordinasikan akses ke objek bersama disinkronkan dan mudah menguap. Kita tahu bahwa kata kunci yang disinkronkan mengimplementasikan kunci bawaan, sedangkan kata kunci yang mudah menguap memastikan visibilitas memori untuk multi-threads. Dalam kebanyakan kasus, mekanisme ini dapat melakukan pekerjaan dengan baik, tetapi mereka tidak dapat menerapkan beberapa fungsi yang lebih maju, seperti tidak dapat mengganggu utas yang menunggu untuk mendapatkan kunci, tidak dapat menerapkan mekanisme kunci yang terbatas waktu, karena tidak dapat menerapkan aturan kunci untuk struktur yang tidak blokir, dll. Dan mekanisme penguncian yang lebih fleksibel ini biasanya memberikan aktivitas atau kinerja yang lebih baik. Oleh karena itu, mekanisme baru telah ditambahkan dalam Java 5.0: Reentrantlock. Kelas Reentrantlock mengimplementasikan antarmuka kunci dan memberikan visibilitas mutex dan memori yang sama seperti yang disinkronkan. Lapisan yang mendasari adalah untuk mencapai sinkronisasi multi-thread melalui AQS. Dibandingkan dengan kunci bawaan, reentrantlock tidak hanya memberikan mekanisme penguncian yang lebih kaya, tetapi juga tidak lebih rendah dari kunci bawaan dalam kinerja (bahkan lebih baik daripada kunci bawaan dalam versi sebelumnya). Setelah berbicara tentang begitu banyak keunggulan Reentrantlock, mari kita temukan kode sumbernya dan lihat implementasinya yang spesifik.
1. Pengantar kata kunci yang disinkronkan
Java menyediakan kunci bawaan untuk mendukung sinkronisasi multi-thread. JVM mengidentifikasi blok kode yang disinkronkan sesuai dengan kata kunci yang disinkronkan. Ketika utas memasuki blok kode yang disinkronkan, itu akan secara otomatis memperoleh kunci. Saat keluar dari blok kode yang disinkronkan, kunci akan secara otomatis dirilis. Setelah satu utas memperoleh kunci, utas lain akan diblokir. Setiap objek Java dapat digunakan sebagai kunci yang mengimplementasikan sinkronisasi. Kata kunci yang disinkronkan dapat digunakan untuk memodifikasi metode objek, metode statis, dan blok kode. Saat memodifikasi metode objek dan metode statis, kunci adalah objek di mana metode berada dan objek kelas. Saat memodifikasi blok kode, objek tambahan perlu disediakan sebagai kunci. Alasan mengapa setiap objek Java dapat digunakan sebagai kunci adalah bahwa objek monitor (manipulasi) dikaitkan di header objek. Ketika utas memasuki blok kode sinkron, itu akan secara otomatis menampung objek monitor, dan ketika keluar, itu akan secara otomatis melepaskan objek monitor. Ketika objek monitor diadakan, utas lain akan diblokir. Tentu saja, operasi sinkronisasi ini diimplementasikan oleh lapisan JVM yang mendasari, tetapi masih ada beberapa perbedaan dalam implementasi yang mendasari metode modifikasi kata kunci yang disinkronkan dan blok kode. Metode modifikasi kata kunci yang disinkronkan secara implisit disinkronkan, yaitu, tidak perlu dikendalikan melalui instruksi bytecode. JVM dapat membedakan apakah suatu metode adalah metode yang disinkronkan berdasarkan bendera akses ACC_SYNCHRONIZed di tabel metode; Sementara kode blok yang dimodifikasi oleh kata kunci yang disinkronkan secara eksplisit disinkronkan, yang mengontrol holding dan pelepasan pipa utas melalui instruksi bytecode monitorexit bytecode. Objek monitor memegang bidang _count secara internal. _count sama dengan 0 berarti pipa tidak diadakan, dan _count lebih besar dari 0 berarti bahwa pipa telah diadakan. Setiap kali utas holding masuk kembali, _Count akan ditambahkan 1, dan setiap kali utas holding keluar, _Count akan dikurangi dengan 1. Ini adalah prinsip implementasi masuk kembali kunci bawaan. Selain itu, ada dua antrian di dalam objek monitor _entrylist dan _waitset, yang sesuai dengan antrian sinkronisasi dan antrian kondisional AQS. Ketika utas gagal mendapatkan kunci, itu akan memblokir di _entrylist. Ketika metode tunggu objek kunci dipanggil, utas akan memasukkan _waitset untuk menunggu. Ini adalah prinsip implementasi sinkronisasi utas dan menunggu kunci untuk kunci bawaan.
2. Perbandingan antara reentrantlock dan disinkronkan
Kata kunci yang disinkronkan adalah mekanisme kunci bawaan yang disediakan oleh Java. Operasi sinkronisasinya diimplementasikan oleh JVM yang mendasari. Reentrantlock adalah kunci eksplisit yang disediakan oleh paket java.util.concurrent, dan operasi sinkronisasi ditenagai oleh sinkronisasi AQS. Reentrantlock menyediakan semantik yang sama tentang penguncian dan memori seperti kunci bawaan, selain itu menyediakan beberapa fitur lain termasuk penantian kunci waktu, penantian kunci interruptible, penguncian yang adil, dan mengimplementasikan penguncian terstruktur non-blok. Selain itu, Reentrantlock juga memiliki keunggulan kinerja tertentu di versi JDK awal. Karena Reentrantlock memiliki begitu banyak keuntungan, mengapa kita harus menggunakan kata kunci yang disinkronkan? Bahkan, banyak orang menggunakan reentrantlock untuk menggantikan pengoperasian kunci kata kunci yang disinkronkan. Namun, kunci bawaan masih memiliki keunggulan sendiri. Kunci bawaan akrab bagi banyak pengembang dan lebih sederhana dan kompak digunakan. Karena kunci eksplisit harus secara manual disebut buka kunci di blok akhirnya, relatif lebih aman untuk menggunakan kunci bawaan. Pada saat yang sama, lebih mungkin untuk meningkatkan kinerja sinkronisasi daripada reentrantlock di masa depan. Karena disinkronkan adalah properti bawaan dari JVM, ia dapat melakukan beberapa optimisasi, seperti optimasi eliminasi kunci untuk objek kunci yang tertutup benang, menghilangkan sinkronisasi kunci bawaan dengan meningkatkan granularitas kunci, dan jika fungsi-fungsi ini diimplementasikan melalui kunci berbasis perpustakaan kelas, tidak ada lagi. Jadi ketika beberapa fitur canggih diperlukan, reentrantlock harus digunakan, yang meliputi: operasi akuisisi kunci yang dapat diuraikan, dapat diserbuki dan interruptible, antrian yang adil, dan kunci struktur non-blok. Jika tidak, disinkronkan harus digunakan terlebih dahulu.
3. Operasi memperoleh dan melepaskan kunci
Pertama -tama mari kita lihat kode sampel menggunakan reentrantlock untuk menambahkan kunci.
public void dosomething () {// standarnya adalah untuk mendapatkan kunci reentrantlock non-fair = baru reentrantlock (); coba {// lock lock.lock () sebelum eksekusi; // Jalankan operasi ...} akhirnya {// lock lock.unlock () akhirnya dirilis; }}Berikut ini adalah API untuk memperoleh dan melepaskan kunci.
// Pengoperasian mendapatkan kunci public void lock () {sync.lock ();} // Pengoperasian pelepasan lock public void unlock () {sync.release (1);}Anda dapat melihat bahwa operasi memperoleh kunci dan melepaskan kunci didelegasikan ke metode kunci dan melepaskan metode objek sinkronisasi masing -masing.
Kelas Publik Reentrantlock mengimplementasikan kunci, java.io.serializable {private final Sync Sync; Sinkronisasi Kelas Statis Abstrak memperluas AbstractQueuedSynchronizer {abstrak void lock (); } // sinkronisasi yang mengimplementasikan kelas akhir statis nonfairsync non-fair static extends Sync {final void lock () {...}} // sinkronisasi yang mengimplementasikan kelas akhir statis statis fairsync memperluas sinkronisasi {final void lock () {...}}}Setiap objek Reentrantlock memegang referensi sinkronisasi tipe. Kelas sinkronisasi ini adalah kelas dalam yang abstrak. Ini mewarisi dari abstractqueuedsynchronizer. Metode kunci di dalamnya adalah metode abstrak. Sinkronisasi variabel anggota Reentrantlock diberi nilai selama konstruksi. Mari kita lihat apa yang dilakukan dua metode konstruktor reentrantlock?
// Konstruktor Parameter Tanpa Publik Reentrantlock () {sync = nonfairsync () baru ();} // Parameterisasi konstruktor publik reentrantlock (boolean fair) {sync = fair? new fairsync (): nonfairsync baru ();}Memanggil konstruktor tanpa parameter default akan menetapkan instance nonfairsync untuk disinkronkan, dan kunci adalah kunci non-fair saat ini. Konstruktor parameter memungkinkan parameter untuk menentukan apakah akan menetapkan instance fairsync atau instance nonfairsync untuk disinkronkan. Nonfairsync dan fairsync keduanya mewarisi dari kelas sinkronisasi dan menulis ulang metode lock (), jadi ada beberapa perbedaan antara kunci yang adil dan kunci non-fair dalam cara mendapatkan kunci, yang akan kita bicarakan di bawah ini. Mari kita lihat operasi melepaskan kunci. Setiap kali Anda memanggil metode buka kunci (), Anda hanya menjalankan operasi sync.release (1). Operasi ini akan menghubungi metode rilis () dari kelas AbstractQueuedSynchronizer. Mari kita tinjau lagi.
// Lepaskan operasi kunci (mode eksklusif) rilis boolean akhir publik (int arg) {// putar kunci kata sandi untuk melihat apakah dapat membuka kunci if (tryrelease (arg)) {// Dapatkan simpul head node h = head; // Jika simpul kepala tidak kosong dan keadaan menunggu tidak sama dengan 0, bangun simpul penerus if (h! = Null && h.waitstatus! = 0) {// bangun simpul penerus node unparkuccessor (h); } return true; } return false;}Metode rilis ini adalah API untuk merilis operasi kunci yang disediakan oleh AQS. Pertama -tama memanggil metode tryrelease untuk mencoba memperoleh kunci. Metode tryrelease adalah metode abstrak, dan logika implementasinya ada dalam sinkronisasi subkelas.
// Cobalah untuk melepaskan boolean tryrelease akhir yang dilindungi kunci (rilis int) {int c = getState () - rilis; // Jika utas yang menahan kunci bukan utas saat ini, pengecualian akan dilemparkan jika (thread.currentThread ()! = GetExclusiveOwnerThread ()) {lempar baru ilegalmonitorstateException (); } boolean free = false; // Jika status sinkronisasi adalah 0, itu berarti bahwa kunci dilepaskan if (c == 0) {// Atur bendera kunci yang dirilis sebagai true free = true; // atur utas yang ditempati ke setExclusiveOwnerThread kosong (null); } setState (c); kembali gratis;}Metode tryrelease ini pertama -tama akan memperoleh keadaan sinkronisasi saat ini, mengurangi keadaan sinkronisasi saat ini dari parameter yang diteruskan ke keadaan sinkronisasi baru, dan kemudian menentukan apakah keadaan sinkronisasi baru sama dengan 0. Jika sama dengan 0, itu berarti bahwa kunci saat ini dilepaskan. Kemudian atur status rilis kunci ke true, lalu hapus utas yang saat ini menempati kunci, dan akhirnya panggil metode SetState untuk mengatur status sinkronisasi baru dan mengembalikan status rilis kunci.
4. Kunci yang adil dan kunci yang tidak adil
Kita tahu contoh spesifik mana yang ditunjukkan reentrantlock berdasarkan sinkronisasi. Selama konstruksi, sinkronisasi variabel anggota akan ditetapkan. Jika nilai ditetapkan ke instance nonfairsync, itu berarti itu adalah kunci non-fair, dan jika nilainya ditetapkan untuk instance fairsync, itu berarti itu adalah kunci yang adil. Jika itu adalah kunci yang adil, utas akan mendapatkan kunci dalam urutan di mana mereka membuat permintaan, tetapi pada kunci yang tidak adil, perilaku cut-in diperbolehkan: Ketika utas meminta kunci yang tidak adil, jika keadaan kunci tersedia pada saat yang sama dengan permintaan dikeluarkan, utas akan melewatkan semua utas menunggu dalam antrian untuk mendapatkan kunci secara langsung. Mari kita lihat cara mendapatkan kunci yang tidak adil.
// Sinkronisasi tidak adil kelas akhir statis nonfairsync memperluas sinkronisasi {// mengimplementasikan metode abstrak kelas induk untuk memperoleh kunci final lock () {// menggunakan metode CAS untuk mengatur status sinkronisasi jika (compareandsetstate (0, 1)) {// Jika pengaturan berhasil, itu berarti bahwa kunci tidak ditempati (0, 1)) {// jika pengaturannya berhasil, itu berarti kunci yang tidak ditempati. } else {// Kalau tidak, itu berarti bahwa kunci telah ditempati, hubungi dapatkan dan biarkan utas mengantri untuk menyinkronkan antrian untuk mendapatkan perolehan (1); }} // Metode untuk mencoba memperoleh lock final boolean tryacquire yang dilindungi (int mengakuisisi) {return nonfairtryacquire (mengakuisisi); }} // memperoleh kunci dalam mode non-intrupt (mode eksklusif) public final void accquire (int arg) {if (! Tryacquire (arg) && AcquireQueued (addWaiter (node.exclusive), arg)) {selfInterrupt (); }}Dapat dilihat bahwa dalam metode kunci kunci yang tidak adil, utas akan mengubah nilai status sinkronisasi dari 0 menjadi 1 pada langkah pertama di CAS. Bahkan, operasi ini setara dengan mencoba memperoleh kunci. Jika perubahan berhasil, itu berarti bahwa utas telah memperoleh kunci sekarang, dan tidak perlu lagi mengantri dalam antrian sinkronisasi lagi. Jika perubahan gagal, itu berarti bahwa kunci belum dirilis ketika utas pertama kali datang, sehingga metode perolehan dipanggil berikutnya. Kita tahu bahwa metode perolehan ini diwarisi dari metode abstractqueuedsynchronizer. Mari kita tinjau metode ini. Setelah utas memasuki metode perolehan, panggilan pertama metode tryacquire untuk mencoba memperoleh kunci. Karena nonfairsync menimpa metode tryacquire dan memanggil metode nonfairtryacquire dari sinkronisasi kelas induk dalam metode ini, metode nonfairtryacquire akan dipanggil di sini untuk mencoba memperoleh kunci. Mari kita lihat apa yang dilakukan metode ini secara khusus.
// Akuisisi tidak adil dari Lock Final Boolean Nonfairtryacquire (int Acquires) {// Dapatkan utas utas saat ini saat ini = thread.currentThread (); // Dapatkan status sinkronisasi saat ini int c = getState (); // Jika status sinkronisasi adalah 0, itu berarti bahwa kunci tidak ditempati jika (c == 0) {// Gunakan CAS untuk memperbarui status sinkronisasi jika (CompareEndsetState (0, Acquires)) {// Setel utas yang saat ini menempati kunci setexclusiveOwnThread (saat ini); Kembali Benar; } // Sebaliknya, ditentukan apakah kunci adalah utas saat ini} lain jika (saat ini == getExclusiveOwnerThread ()) {// Jika kunci dipegang oleh utas saat ini, secara langsung memodifikasi status sinkronisasi saat ini int nextc = C + memperoleh; if (nextc <0) {lempar kesalahan baru ("jumlah kunci maksimum terlampaui"); } setState (nextc); Kembali Benar; } // Jika kunci bukan utas saat ini, kembalikan bendera kegagalan Return false;}Metode Nonfairtryacquire adalah metode sinkronisasi. Kita dapat melihat bahwa setelah utas memasuki metode ini, pertama -tama memperoleh keadaan sinkronisasi. Jika keadaan sinkronisasi adalah 0, gunakan operasi CAS untuk mengubah keadaan sinkronisasi. Bahkan, ini untuk mendapatkan kunci lagi. Jika keadaan sinkronisasi bukan 0, itu berarti kunci ditempati. Pada saat ini, pertama -tama kita akan menentukan apakah utas yang menahan kunci adalah utas saat ini. Jika demikian, keadaan sinkronisasi akan ditingkatkan dengan 1. Jika tidak, operasi mencoba memperoleh kunci akan gagal. Jadi metode Addwaaiter akan dipanggil untuk menambahkan utas ke antrian sinkronisasi. Singkatnya, dalam mode kunci yang tidak adil, utas akan mencoba memperoleh dua kunci sebelum memasuki antrian sinkronisasi. Jika akuisisi berhasil, ia tidak akan memasukkan antrian antrian antrian sinkronisasi, jika tidak ia akan memasukkan antrian antrian antrian sinkronisasi. Selanjutnya, mari kita lihat cara mendapatkan kunci yang adil.
// Synchronizer yang mengimplementasikan Fair Static Static Final Class FairSync memperluas Sync {// mengimplementasikan metode abstrak dari kelas induk untuk memperoleh kunci void lock () {// panggilan mendapatkan akuisisi dan membiarkan utas mengantarkan untuk menyinkronkan antrian untuk mendapatkan memperoleh (1); } // Cobalah untuk memperoleh lock final boolean tryacquire yang dilindungi (int acquires) {// dapatkan utas saat ini saat ini arus current = thread.currentThread (); // Dapatkan status sinkronisasi saat ini int c = getState (); // Jika status sinkronisasi 0 berarti bahwa kunci tidak ditempati jika (c == 0) {// bertahan apakah ada simpul ke depan dalam antrian sinkronisasi jika (! HasqueuedPredecessors () && compareANDSetState (0, mengakuisisi)) {// jika tidak ada node ke depan dan status Synchronication yang berhasil (0, diperoleh dengan sukses) {// jika tidak ada node ke depan dan Synchronication State yang berhasil (0, Acquires)), jika tidak ada node ke depan dan Synchronication State yang berhasil, setExclusiveOwnerThread (saat ini); Kembali Benar; } // Sebaliknya, tentukan apakah utas saat ini menahan kunci} lain jika (saat ini == getExclusiveOwnerThread ()) {// Jika utas saat ini menahan kunci, secara langsung memodifikasi status sinkronisasi int nextc = c + mengakuisisi; if (nextc <0) {lempar kesalahan baru ("jumlah kunci maksimum terlampaui"); } setState (nextc); Kembali Benar; } // Jika utas saat ini tidak menahan kunci, akuisisi gagal mengembalikan false; }} Saat memanggil metode kunci dari kunci adil, metode perolehan akan dipanggil secara langsung. Demikian pula, metode Acquire pertama -tama memanggil metode fairsync menulis ulang tryacquire untuk mencoba memperoleh kunci. Dalam metode ini, nilai keadaan sinkronisasi pertama kali diperoleh. Jika keadaan sinkronisasi adalah 0, itu berarti bahwa kunci dilepaskan saat ini. Perbedaan dari kunci yang tidak adil adalah pertama -tama akan memanggil metode HasqueuedPredecessors untuk memeriksa apakah seseorang mengantri dalam antrian sinkronisasi. Jika tidak ada yang mengantri, nilai status sinkronisasi akan dimodifikasi. Anda dapat melihat bahwa kunci adil mengadopsi metode kesopanan di sini alih -alih memperoleh kunci segera. Kecuali untuk langkah ini yang berbeda dari kunci yang tidak adil, operasi lain adalah sama. Singkatnya, kita dapat melihat bahwa kunci adil hanya memeriksa status kunci sekali sebelum memasuki antrian sinkronisasi. Bahkan jika Anda menemukan bahwa kunci terbuka, Anda tidak akan segera mendapatkannya. Sebaliknya, Anda akan membiarkan utas dalam antrian sinkronisasi mendapatkannya terlebih dahulu. Oleh karena itu, dapat dipastikan bahwa urutan di mana semua utas memperoleh kunci di bawah kunci wajar adalah yang pertama dan kemudian tiba, yang juga memastikan keadilan mendapatkan kunci.
Jadi mengapa kita tidak ingin semua kunci menjadi adil? Bagaimanapun, keadilan adalah perilaku yang baik, dan ketidakadilan adalah perilaku yang buruk. Karena operasi penangguhan dan bangun utas memiliki overhead yang besar, itu mempengaruhi kinerja sistem, terutama dalam hal persaingan sengit, kunci yang adil akan menyebabkan seringnya penangguhan dan operasi benang, sementara kunci non-fair dapat mengurangi operasi tersebut, sehingga mereka akan lebih baik daripada kunci yang adil dalam kinerja. Selain itu, karena sebagian besar utas menggunakan kunci untuk waktu yang sangat singkat, dan operasi bangun utas akan memiliki penundaan, ada kemungkinan bahwa Thread B akan segera memperoleh kunci dan melepaskan kunci setelah menggunakannya. Ini mengarah pada situasi win-win. Momen ketika utas A memperoleh kunci tidak tertunda, tetapi Thread B menggunakan kunci terlebih dahulu dan throughputnya juga telah ditingkatkan.
5. Mekanisme implementasi antrian bersyarat
Ada beberapa cacat dalam antrian kondisi bawaan. Setiap kunci bawaan hanya dapat memiliki satu antrian kondisi terkait, yang menyebabkan banyak utas menunggu predikat kondisi yang berbeda pada antrian kondisi yang sama. Kemudian, setiap saat memberi tahu semua dipanggil, semua utas yang menunggu akan terbangun. Ketika utas bangun, ia menemukan bahwa itu bukan kondisi predikat yang sedang menunggu, dan itu akan ditangguhkan. Hal ini menyebabkan banyak operasi yang tidak berguna dan menangguhkan operasi, yang akan menyia-nyiakan banyak sumber daya sistem dan mengurangi kinerja sistem. Jika Anda ingin menulis objek bersamaan dengan beberapa predikat bersyarat, atau jika Anda ingin mendapatkan lebih banyak kontrol daripada visibilitas antrian bersyarat, Anda perlu menggunakan kunci dan kondisi eksplisit alih-alih kunci bawaan dan antrian bersyarat. Suatu kondisi dan kunci dikaitkan bersama-sama, seperti antrian kondisi dan kunci bawaan. Untuk membuat suatu kondisi, Anda dapat menghubungi metode lock.newCondition pada kunci terkait. Pertama -tama mari kita lihat contoh menggunakan kondisi.
kelas publik BoundedBuffer {final lock lock = baru reentrantlock (); Kondisi akhir itfull = lock.newcondition (); // Kondisi Predikat: Kondisi akhir yang mencolok notempty = lock.newcondition (); // Kondisi Predikat: Notempty Final Object [] item = Objek baru [100]; Int Putptr, Takeptr, Count; // metode produksi public void put (objek X) melempar InterruptedException {lock.lock (); coba {while (count == items.length) notfull.Await (); // Antrian penuh, dan utasnya menunggu item [putptr] pada antrian yang mencolok. item [putptr] = x; if (++ putptr == items.length) putptr = 0; ++ Count; notempty.signal (); // Produksi berhasil, bangun simpul antrian yang tidak tetap} akhirnya {lock.unlock (); }} // Metode Mengkonsumsi Objek Publik Take () melempar InterruptedException {lock.lock (); coba {while (count == 0) notempty.aWait (); // antriannya kosong, utas menunggu objek x = item [takePtr] pada antrian yang tidak tetap; if (++ takePtr == items.length) takePtr = 0; --menghitung; tistrull.signal (); // Konsumsi berhasil, bangunkan simpul pengembalian antrian yang mencolok x; } akhirnya {lock.unlock (); }}}Objek kunci dapat menghasilkan antrian kondisi berganda, dan dua antrian kondisi dihasilkan di sini tokoh dan tidak ada. Saat wadah penuh, utas yang memanggil metode put perlu diblokir. Tunggu sampai predikat kondisi benar (wadah tidak puas) bangun dan terus mengeksekusi; Saat wadah kosong, utas yang memanggil metode Take perlu diblokir. Tunggu sampai predikat kondisi benar (wadah tidak kosong) bangun dan terus mengeksekusi. Dua jenis utas ini menunggu sesuai dengan predikat kondisi yang berbeda, sehingga mereka akan memasukkan dua antrian kondisi berbeda untuk diblokir, dan menunggu sampai waktu yang tepat sebelum bangun dengan memanggil API pada objek kondisi. Berikut ini adalah kode implementasi dari metode NewCondition.
// Buat Kondisi Antrian Kondisi Publik NewCondition () {return sync.newcondition ();} Abstrak Sinkronisasi kelas statis meluas AbstractQueuedSynchronizer {// Buat Objek Kondisi Baru Final ConditionObject newCondition () {return new conditionObject (); }}Implementasi antrian kondisi pada reentrantlock didasarkan pada abstractqueuedsynchronizer. Objek kondisi yang kami peroleh saat memanggil metode NewCondition adalah instance dari ConditionObject kelas internal AQS. Semua operasi dengan kondisi antrian dilakukan dengan memanggil API yang disediakan oleh ConditionObject. Untuk implementasi spesifik dari ConditionObject, Anda dapat memeriksa artikel saya "Java Concurrency Series [4] ----- AbstractQueuedSynchronizer Analisis Kode Sumber Analisis Kondisional" dan saya tidak akan mengulanginya di sini. Pada titik ini, analisis kami tentang kode sumber Reentrantlock telah berakhir. Saya berharap bahwa membaca artikel ini akan membantu pembaca memahami dan menguasai Reentrantlock.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.