Melalui analisis dari tiga artikel sebelumnya, kami memiliki pemahaman yang mendalam tentang struktur internal dan beberapa konsep desain abstractqueuedsynchronizer, dan kami tahu bahwa AbstractQueuedSynchronizer mempertahankan keadaan sinkronisasi dan dua area antrian, yang masing -masing merupakan antrian sinkron dan antrian bersyarat. Mari kita gunakan toilet umum sebagai analogi. Antrian sinkronisasi adalah area antrian utama. Jika toilet umum tidak terbuka, semua orang yang ingin memasuki toilet harus mengantri di sini. Kondisi antrian terutama ditetapkan untuk kondisi menunggu. Mari kita bayangkan bahwa jika seseorang akhirnya berhasil mendapatkan kunci dan memasuki toilet melalui antrian, tetapi menemukan bahwa ia tidak membawa kertas toilet sebelum kenyamanan. Meskipun dia tidak berdaya saat menghadapi situasi ini, itu juga harus menerima fakta ini. Pada saat ini, ia harus keluar dan menyiapkan kertas toilet terlebih dahulu (masukkan antrian kondisi untuk menunggu). Tentu saja, sebelum keluar, kunci harus dilepaskan sehingga orang lain dapat masuk. Setelah menyiapkan kertas toilet (kondisinya dipenuhi), ia harus kembali ke antrian sinkron untuk mengantri lagi. Tentu saja, tidak semua orang memasuki ruangan tidak membawa kertas toilet. Mungkin ada alasan lain bahwa mereka harus mengganggu operasi dan mengantri dalam kondisi antrian terlebih dahulu. Oleh karena itu, dapat ada beberapa antrian kondisi, dan antrian kondisi yang berbeda ditetapkan sesuai dengan kondisi tunggu yang berbeda. Kondisi antrian adalah daftar tertaut satu arah. Antarmuka kondisi mendefinisikan semua operasi dalam antrian kondisi. Kelas ConditionObject di dalam AbstractQueuedSynchronizer mengimplementasikan antarmuka kondisi. Mari kita lihat operasi apa yang ditentukan oleh antarmuka kondisi.
Kondisi Antarmuka Publik {// Menunggu respons terhadap interupsi utas void wait () melempar interruptException; // menunggu untuk tidak merespons interupsi utas void stabil interupricly (); // Pengaturan Kondisi Menunggu Waktu Relatif (Tanpa Putaran) Long Awaitnanos (Long Nanostimeout) melempar interruptedException; // Pengaturan Kondisi Menunggu Waktu Relatif (Spin) Boolean menunggu (lama, unit TimeUnit) melempar interruptedException; // Pengaturan Kondisi Menunggu Waktu Absolut Boolean Awaituntil (Batas Waktu Tanggal) Melempar Exception Interrupted; // Bangunkan sinyal head node void () dalam antrian kondisi; // Bangun semua node dari kondisi antrian batal sinyal (); }Meskipun antarmuka kondisi mendefinisikan begitu banyak metode, itu dibagi menjadi dua kategori secara total. Metode yang dimulai dengan menunggu adalah metode yang masuk ke utas antrian kondisi dan menunggu, dan metode yang dimulai dengan sinyal adalah metode yang "membangunkan" utas dalam antrian kondisi. Perlu dicatat di sini bahwa memanggil metode sinyal mungkin atau mungkin tidak membangunkan utas. Ketika utas akan dibangunkan tergantung pada situasinya, seperti yang akan dibahas nanti, tetapi memanggil metode sinyal pasti akan memindahkan utas dari antrian bersyarat ke ekor antrian sinkronisasi. Demi kenyamanan narasi, kita tidak akan mengkhawatirkannya untuk saat ini. Kami akan memanggil metode sinyal pengoperasian utas antrian bersyarat. Harap dicatat bahwa ada 5 jenis metode menunggu, yaitu, waiting interrupt utas respons, interupsi utas non-respons menunggu, waktu relatif non-spin menunggu, putaran waktu relatif menunggu, dan waktu absolut menunggu; Hanya ada dua jenis metode sinyal, yaitu, pengoperasian hanya membangkitkan simpul kepala antrian dan membangunkan semua node dari antrian kondisi. Jenis metode yang sama pada dasarnya sama. Karena keterbatasan ruang, tidak mungkin dan tidak perlu membicarakan metode ini dengan cermat. Kita hanya perlu memahami satu metode representatif dan kemudian melihat metode lain untuk memahaminya. Jadi dalam artikel ini saya hanya akan berbicara tentang metode menunggu dan metode sinyal secara rinci. Metode lain tidak akan dibahas secara rinci, tetapi akan memposting kode sumber untuk referensi Anda.
1. Tunggu respons terhadap kondisi interupsi utas
// menunggu sebagai tanggapan terhadap kondisi utas interupsi public final void menunggu () melempar interruptedException {// jika utas terganggu, pengecualian dilemparkan jika (thread.interrupted ()) {lempar interruptException baru (); } // Tambahkan utas saat ini ke ekor simpul antrian kondisi simpul = addConditionwaiter (); // Lepaskan Lengkap Kunci Sebelum Memasuki Kondisi Tunggu int SavedState = FullRelease (node); int interruptMode = 0; // Utas telah menunggu secara kondisional dalam loop sementara (! Isonsyncqueue (node)) {// utas yang menunggu secara kondisional ditangguhkan di sini, ada beberapa kasus di mana utas dibangunkan: // 1. Node depan dari antrian sinkronisasi telah dibatalkan // 2. Atur keadaan simpul depan dari antrian sinkronisasi ke sinyal gagal // 3. Node saat ini dibangunkan setelah node depan melepaskan kunci. // Utas saat ini segera memeriksa apakah itu terganggu. Jika demikian, itu berarti bahwa node membatalkan kondisi menunggu. Pada saat ini, simpul perlu dipindahkan dari kondisi antrian jika ((interruptMode = checkInterruptwhileWaiting (node))! = 0) {break; }} // Setelah utas terbangun, itu akan memperoleh kunci dalam mode eksklusif jika (diakuisisi (node, savedState) && interruptMode! = Throw_ie) {interruptMode = reintrupt; } // Operasi ini terutama untuk mencegah utas mengganggu sebelum sinyal, menghasilkan tidak ada pemutusan dari kondisi antrian jika (node.nextwaiter! = Null) {unlinkCancelledwaiters (); } // pemrosesan interupsi yang merespons mode interupsi jika (interruptMode! = 0) {ReportInterruptAfterWait (InterruptMode); }}Ketika utas memanggil metode menunggu, utas saat ini akan dibungkus sebagai simpul dan ditempatkan di ekor antrian kondisi. Dalam metode AddConditionWaiter, jika kondisi antrian kondisi antrian ditemukan dibatalkan, metode UnlinkCancelledwaiters akan dipanggil untuk menghapus semua node yang dibatalkan dari antrian kondisi. Langkah ini adalah persiapan untuk memasukkan node. Setelah memastikan bahwa status simpul ekor juga merupakan kondisi, simpul baru akan dibuat untuk membungkus utas saat ini dan meletakkannya di ekor antrian kondisi. Perhatikan bahwa proses ini hanya menambahkan node ke ekor antrian sinkronisasi tanpa utas menangguhkan.
Langkah 2: Lepaskan kunci sepenuhnya
// Lepaskan Lengkap Lock Final Int FullRelease (simpul simpul) {boolean gagal = true; coba {// dapatkan status sinkronisasi saat ini int savedState = getState (); // Gunakan status sinkronisasi saat ini untuk melepaskan kunci IF (rilis (SavedState)) {FAILT = FALSE; // Jika kunci berhasil dirilis, return SavedState; } else {// Jika kunci dilepaskan gagal, lempar pengecualian runtime lempar baru ilegalmonitorstateException (); }} akhirnya {// Pastikan node diatur ke status batal jika (gagal) {node.waitstatus = node.cancelled; }}}Setelah membungkus utas saat ini ke dalam sebuah node dan menambahkannya ke ekor antrian kondisi, metode FullRelease dipanggil untuk melepaskan kunci. Perhatikan bahwa metode bernama FullRelease digunakan untuk sepenuhnya melepaskan kunci, karena kunci itu masuk kembali, jadi Anda perlu melepaskan kunci sebelum menunggu bersyarat, jika tidak, orang lain tidak akan dapat memperoleh kunci. Jika kunci dilepaskan gagal, pengecualian runtime akan dilemparkan. Jika kunci berhasil dirilis, ia akan kembali ke keadaan sinkronisasi sebelumnya.
Langkah 3: Buat kondisi menunggu
// utas telah menunggu di loop while while (! Isonsyncqueue (node)) {// utas yang menunggu kondisi ditangguhkan di sini. Ada beberapa kasus di mana utas dibangunkan: // 1. Node depan dari antrian sinkronisasi telah dibatalkan // 2. Atur keadaan simpul depan dari antrian sinkronisasi ke sinyal gagal // 3. Node saat ini dibangunkan setelah node depan melepaskan kunci. Locksupport.park (ini); // Utas saat ini bangun segera untuk memeriksa apakah itu terganggu. Jika demikian, itu berarti bahwa node membatalkan kondisi menunggu. Pada saat ini, simpul perlu dipindahkan dari kondisi antrian jika ((interruptMode = checkInterruptwhileWaiting (node))! = 0) {break; }} // Periksa situasi interupsi utas ketika kondisi menunggu pemeriksaan intertrupruptwhilewaiting (simpul simpul) {// Permintaan interupsi adalah sebelum operasi sinyal: throw_ie // Permintaan interupsi adalah setelah operasi sinyal: menguatkan // tidak ada permintaan interupsi yang diterima selama periode ini: 0 Thread kembali. (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;}//Transfer the node that cancels the condition waiting from the condition queue to the synchronization queue final boolean transferAfterCancelledWait(Node node) { //If this CAS operation is successful, it means that the interrupt occurs before the signal method if (compareAndSetWaitStatus(node, Node.condition, 0)) {// Setelah modifikasi status berhasil, masukkan node ke dalam ekor antrian sinkronisasi enq (node); Kembali Benar; } // Ini menunjukkan bahwa operasi CAS gagal, menunjukkan bahwa interupsi terjadi setelah metode sinyal saat (! Isonsyncqueue (node)) {// Jika metode sinal belum mentransfer node ke antrian sinkronisasi, tunggu thread.yield (); } return false;}Setelah dua operasi di atas selesai, ia akan memasuki loop sementara. Anda dapat melihat bahwa loop sementara pertama panggilan locksupport.park (ini) untuk menggantung utas, sehingga utas akan diblokir di sini sepanjang waktu. Setelah memanggil metode sinyal, cukup transfer node dari antrian bersyarat ke antrian sinkronisasi. Apakah utas akan dibangunkan tergantung pada situasinya. Jika Anda menemukan bahwa node depan dalam antrian sinkronisasi dibatalkan saat mentransfer node, atau keadaan simpul maju diperbarui ke sinyal gagal, kedua kasus akan segera membangunkan utas. Kalau tidak, utas yang sudah ada dalam antrian sinkronisasi tidak akan terbangun di akhir metode sinyal, tetapi akan menunggu sampai simpulnya terbangun. Tentu saja, selain memanggil metode sinyal untuk bangun, utas juga dapat menanggapi interupsi. Jika utas menerima permintaan interupsi di sini, itu akan terus mengeksekusi. Anda dapat melihat bahwa setelah utas bangun, itu akan segera memeriksa apakah itu dibangunkan oleh interupsi atau melalui metode sinyal. Jika dibangunkan oleh interupsi, itu juga akan mentransfer node ini ke antrian sinkronisasi, tetapi dicapai dengan memanggil metode TransferAfterCancelledWait. Setelah eksekusi terakhir dari langkah ini, interupsi akan dikembalikan dan loop sementara akan melompat keluar.
Langkah 4: Operasi setelah node dihapus dari antrian kondisi
// Setelah utas bangun, itu akan memperoleh kunci dalam mode eksklusif jika (diakuisisi (node, savedState) && interruptMode! = Throw_ie) {interruptMode = reunterrupt;} // operasi ini terutama untuk mencegah utas dari gangguan sebelum sinyal dan menyebabkan kontak tidak ada kontak dengan kondisi queue if (node. UNLINKCANCELLEDWAITers ();} // Pemrosesan interupsi yang merespons mode interupsi jika (interruptMode! = 0) {ReportInterruptAfterWait (interruptMode);} // Setelah mengakhiri kondisi menunggu, Interrupting PROSESSEDECECECECECECECECECECECCECECECECCECECECECECCEFECECCEFECECCECTECCECTECCECTECCECTECCECTECCECTECCECTECCECTECTECECTECCECTECE FORMERCRECECTICE, pengecualian dilemparkan jika (interruptMode == throw_ie) {throw new InterruptException (); // Jika mode interupsi berulang, itu akan menggantung sendiri} lain jika (interruptMode == reintrupt) {selfinterrupt (); }}Ketika utas mengakhiri loop whene, yaitu kondisi menunggu, itu akan kembali ke antrian sinkronisasi. Apakah itu karena memanggil metode sinyal kembali atau karena gangguan utas, node pada akhirnya akan berada dalam antrian sinkron. Pada saat ini, metode yang diperoleh akan dipanggil untuk melakukan operasi mendapatkan kunci dalam antrian sinkronisasi. Kami telah membahas metode ini secara rinci dalam artikel Mode Eksklusif. Dengan kata lain, setelah simpul keluar dari kondisi antrian, itu dengan patuh pergi ke set kunci dalam mode eksklusif. Setelah node ini memperoleh kunci lagi, ia akan menghubungi Metode ReportInterruptAfterWait untuk merespons berdasarkan situasi interupsi selama periode ini. Jika interupsi terjadi sebelum metode sinyal, InterruptMode adalah Throw_ie, dan pengecualian akan dilemparkan setelah kunci diperoleh lagi; Jika interupsi terjadi setelah metode sinyal, interruptMode berlanjut, dan akan terganggu lagi setelah kunci diperoleh lagi.
2. Menunggu non-respons untuk mengarahkan interupsi
// menunggu public final void AwaitUninterrupTIble () {// Tambahkan utas saat ini ke ekor node node antrian kondisi = addConditionWaiter (); // Lepaskan Lengkap Kunci dan kembalikan status sinkronisasi saat ini int savedState = fullrelease (node); Boolean terputus = false; // node secara kondisional menunggu di loop while while (! Isonsyncqueue (node)) {// Semua utas dalam antrian kondisi ditangguhkan di sini locksupport.park (ini); // utas bangun dan menemukan bahwa interupsi tidak akan segera merespons jika (thread.interrupted ()) {interrupted = true; }} if (AcquireQueued (node, SavedState) || Diinterupsi) {// Menanggapi semua permintaan interupsi di sini, jika salah satu dari dua kondisi berikut dipenuhi, itu akan menggantung sendiri // 1. Utas menerima permintaan interupsi saat kondisinya menunggu // 2. Utas menerima permintaan interupsi dalam metode selfintrupt () yang diperoleh; }}3. Atur kondisi waktu relatif menunggu (tidak ada putaran)
// Atur kondisi waktu menunggu (waktu relatif), dan jangan lakukan spin menunggu publik final lama awaitnanos (long nanostimeout) melempar interruptedException {// jika utas terganggu, pengecualian dilemparkan jika (thread.echerrupted ()) {throw new interruptEcception (); } // Tambahkan utas saat ini ke ekor simpul antrian kondisi simpul = addConditionwaiter (); // Lepaskan Lengkap Kunci sebelum memasuki kondisi menunggu int savedState = fullrelease (node); Long Lasttime = System.nanoTime (); int interruptMode = 0; while (! isonsyncqueue (node)) {// menilai apakah batas waktu digunakan jika (nanoSticeOut <= 0l) {// jika batas waktu telah selesai, Anda perlu menjalankan Operasi Kondisi Batalkan TransferFterCancelledWait (Node); merusak; } // Gantung utas saat ini untuk jangka waktu tertentu, utas dapat dibangunkan selama periode ini, atau mungkin bangun dengan sendirinya locksupport.parknanos (ini, nanostimeout); // Periksa informasi interupsi terlebih dahulu setelah utas bangun jika ((interruptMode = checkInterruptwhileWaiting (node))! = 0) {break; } long now = system.nanoTime (); // Waktu batas waktu dikurangi waktu tunggu dari kondisi nanostimeout - = sekarang - terakhir; terakhir kali = sekarang; } // Setelah utas terbangun, itu akan memperoleh kunci dalam mode eksklusif jika (diakuisisi (node, saveDstate) && interruptMode! = Throw_ie) {interruptMode = reintrupt; } // Karena metode TransferAfterCancelledWait tidak mengosongkan Nextwaaiter, semua yang Anda butuhkan untuk membersihkan di sini jika (node.nextwaiter! = Null) {unlinkCancelledwaiters (); } // pemrosesan interupsi yang merespons mode interupsi jika (interruptMode! = 0) {ReportInterruptAfterWait (InterruptMode); } // mengembalikan sisa waktu pengembalian nanosTimeout - (system.nanoTime () - terakhir);}4. Atur kondisi waktu relatif menunggu (putaran)
// Atur kondisi waktu tunggu (waktu relatif), lakukan spin tunggu public final boolean menunggu (lama, unit timeunit) melempar interruptedException {if (unit == null) {lempar nullpointerException baru (); } // Dapatkan milidetik dari batas waktu nanostimeout = unit.tonanos (waktu); // Jika utas terganggu, pengecualian dilemparkan jika (thread.interrupted ()) {lempar interruptedException baru (); } // Tambahkan utas saat ini ke ekor simpul antrian kondisi simpul = addConditionwaiter (); // Lepaskan Lengkap Kunci sebelum memasukkan kondisi untuk menunggu int savedState = FullRelease (node); // Dapatkan milidetik dari waktu saat ini lama terakhir = System.nanoTime (); Boolean Timedout = false; int interruptMode = 0; while (! isonsyncqueue (node)) {// Jika batas waktu waktunya, Anda perlu melakukan operasi penunggu kondisi batal jika (nanoSTimeout <= 0l) {timedout = transferFterCancelledWait (node); merusak; } // Jika waktu batas waktu lebih besar dari waktu putaran, utas akan ditangguhkan untuk jangka waktu tertentu jika (nanostimeout> = spinforTimeOutThreshold) {locksupport.parknanos (ini, nanostimmeout); } // Setelah utas bangun, periksa informasi interupsi terlebih dahulu jika ((interruptMode = checkInterruptwhilewaiting (node))! = 0) {break; } long now = system.nanoTime (); // Waktu batas waktu setiap kali mengurangi waktu kondisi menunggu nanostimeout - = sekarang - terakhir; terakhir kali = sekarang; } // Setelah utas terbangun, itu akan memperoleh kunci dalam mode eksklusif jika (diakuisisi (node, saveDstate) && interruptMode! = Throw_ie) {interruptMode = reintrupt; } // Karena metode TransferAfterCancelledWait tidak mengosongkan Nextwaaiter, semua yang Anda butuhkan untuk membersihkan di sini jika (node.nextwaiter! = Null) {UNLINKCANCELLEDWAITers (); } // pemrosesan interupsi yang merespons mode interupsi jika (interruptMode! = 0) {ReportInterruptAfterWait (InterruptMode); } // kembalikan apakah bendera batas waktu kembali! Timeedout;}5. Tetapkan kondisi waktu absolut menunggu
// Tetapkan kondisi waktu tunggu (waktu absolut) Boolean akhir publik Awaituntil (Tanggal Tanggal) melempar InterruptedException {if (batas waktu == null) {lempar nullpointerException baru (); } // Dapatkan milidetik dari waktu absolut lama absTime = Deadline.gettime (); // Jika utas terganggu, pengecualian dilemparkan jika (thread.interrupted ()) {lempar interruptedException baru (); } // Tambahkan utas saat ini ke ekor simpul antrian kondisi simpul = addConditionwaiter (); // Lepaskan Lengkap Kunci Sebelum Memasuki Kondisi Tunggu int SavedState = FullRelease (node); Boolean Timedout = false; int interruptMode = 0; while (! isonsyncqueue (node)) {// Jika batas waktu, Anda perlu melakukan operasi penunggu kondisi batal jika (System.currentTimeMillis ()> absTime) {timedout = transferFterCancelledWait (node); merusak; } // Gantung utas untuk jangka waktu tertentu, di mana utasnya dapat dibangunkan, atau mungkin sudah waktunya untuk bangun dengan sendirinya locksupport.parkuntil (ini, abstime); // Periksa informasi interupsi terlebih dahulu setelah utas bangun ((interruptMode = checkInterruptwhileWaiting (node))! = 0) {break; }} // Setelah utas terbangun, itu akan memperoleh kunci dalam mode eksklusif jika (diakuisisi (node, savedState) && interruptMode! = Throw_ie) {interruptMode = reintrupt; } // Karena metode TransferAfterCancelledWait tidak mengosongkan Nextwaaiter, semua yang Anda butuhkan untuk membersihkan di sini jika (node.nextwaiter! = Null) {unlinkCancelledwaiters (); } // pemrosesan interupsi yang merespons mode interupsi jika (interruptMode! = 0) {ReportInterruptAfterWait (InterruptMode); } // kembalikan apakah bendera batas waktu kembali! Timeedout;}6. Bangunkan simpul kepala dalam antrian bersyarat
// Bangunkan simpul berikutnya dalam kondisi antrian public final void sinyal () {// menilai apakah utas saat ini memegang kunci jika (! IsHeldexClusively ()) {melempar IllegalmonitorStateException () baru; } Node first = firstWaiter; // Jika ada queueer dalam kondisi antrian jika (pertama! = Null) {// Bangunkan simpul kepala dalam kondisi antrian kondisi (pertama); }} // Bangunkan simpul kepala dalam kondisi antrian private void dosignal (node pertama) {do {// 1. Pindahkan referensi FirstWaiter satu per satu if ((firstWaiter = first.nextwaaiter) == null) {lastwaaiter = null; } // 2. Kosongkan referensi simpul penerus simpul head first.nextwaaiter = null; // 3. Transfer node kepala ke antrian sinkronisasi, dan dimungkinkan untuk membangunkan utas setelah transfer selesai // 4. Jika Operasi TransferForsignal gagal, bangun simpul berikutnya} while (! TransferForsignal (pertama) && (first = firstWaiter)! = Null);} // Transfer node yang ditentukan dari kondisi antrian ke node Sinkronisasi (Node Node) {// set dari NODEUS TOKEITE PERTANYAAN (NOD NODE NODEUS (NODE NODEUS (NODE NODEUS (NODE NODEUS (NODE NODEUS (NODE NODEUS (NODE NODEUS, Node.condition, 0)) {// Jika operasi untuk memperbarui status gagal, mengembalikan FALSE secara langsung // Mungkin metode TransferAfterCancelledWait mengubah status terlebih dahulu, menyebabkan operasi CAS ini gagal kembali False; } // Tambahkan simpul ini ke ekor simpul antrian sinkronisasi p = enq (node); int ws = p.waitstatus; if (ws> 0 ||! compareEndsetwaitstatus (p, ws, node.signal)) {// utas saat ini akan terbangun ketika situasi berikut terjadi // 1. Node Forward berada di negara bagian Batal // 2. Keadaan node yang diperbarui adalah operasi sinyal gagal locksupport.unpark (node.thread); } return true;}Dapat dilihat bahwa inti utama dari metode sinyal adalah memanggil metode transferForsignal. Dalam metode transferForsignal, pertama -tama gunakan operasi CAS untuk mengatur keadaan simpul dari kondisi ke 0, dan kemudian hubungi metode ENQ untuk menambahkan node ke ekor antrian sinkronisasi. Kita melihat pernyataan penilaian berikutnya. Pernyataan penilaian ini terutama digunakan untuk menentukan kapan utas akan dibangunkan. Jika kedua situasi ini terjadi, utas akan segera terbangun. Salah satunya adalah ketika ditemukan bahwa keadaan simpul sebelumnya dibatalkan, dan yang lainnya adalah ketika keadaan simpul sebelumnya gagal memperbarui. Kedua kasus akan segera membangunkan utas, jika tidak itu akan dilakukan dengan hanya mentransfer node dari antrian bersyarat ke antrian sinkronisasi, dan tidak akan segera membangunkan utas di node. Metode SignalAll kira -kira sama, kecuali bahwa ia meluncur melalui semua node dalam antrian bersyarat dan mentransfernya ke antrian sinkron. Metode mentransfer node masih memanggil metode transferForsignal.
7. Bangun semua node dari antrian kondisi
// bangun semua node di balik kondisi antrian public void sinyalAll () {// menilai apakah utas saat ini memegang kunci jika (! IsHeldexClusively ()) {melempar IllegalmonitorStateException () baru; } // Dapatkan simpul header antrian Kondisi First = FirstWaiter; if (first! = null) {// bangun semua node dari kondisi antrian dosignalall (pertama); }} // Bangun semua node dari kondisi antrian private void dosignalall (node pertama) {// pertama -tama kosongkan referensi node header dan node tail lastwaaiter = firstWaiter = null; do {// dapatkan referensi simpul penerus First = first.nextwaaiter; // Kosongkan referensi node selanjutnya yang akan ditransfer terlebih dahulu.nextwaaiter = null; // Transfer node dari antrian bersyarat ke antrian sinkronisasi transferforsignal (pertama); // Arahkan referensi ke simpul berikutnya First = Next; } while (first! = null);}Pada titik ini, seluruh analisis kode sumber AbstractQueuedSynchronizer kami sudah berakhir. Saya percaya bahwa melalui keempat analisis ini, semua orang dapat menguasai dan memahami AQS dengan lebih baik. Kategori ini memang sangat penting karena merupakan landasan dari banyak kategori sinkronisasi lainnya. Karena level terbatas dan kemampuan ekspresi penulis, jika tidak ada pernyataan yang jelas atau pemahaman yang tidak memadai, harap perbaiki dalam waktu dan diskusikan dan pelajari bersama. Anda dapat meninggalkan pesan untuk membaca masalah di bawah ini. Jika Anda memerlukan kode sumber komentar AQS, Anda juga dapat menghubungi penulis untuk memintanya.
Catatan: Semua analisis di atas didasarkan pada JDK1.7, dan akan ada perbedaan antara versi yang berbeda, pembaca perlu memperhatikan.
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.