Dalam pembangunan program, kadangkala perlu menangguhkan beberapa operasi pemulaan objek berkos tinggi dan hanya memulakannya apabila objek ini digunakan kes, anda boleh Gunakan penguncian yang disemak dua kali untuk menangguhkan operasi pemulaan objek. Penguncian semak dua kali ialah corak reka bentuk perisian yang direka untuk mengurangkan persaingan dan penyegerakan overhed dalam sistem serentak Berdasarkan corak tunggal biasa, ia mula-mula menentukan sama ada objek telah dimulakan, dan kemudian memutuskan sama ada untuk menguncinya. Walaupun penguncian yang disemak dua kali menyelesaikan masalah yang terdedah kepada ralat dan tidak selamat daripada corak tunggal biasa dalam persekitaran berbilang benang, masih terdapat beberapa bahaya tersembunyi. Berikut mengambil kod sumber bahasa JAVA sebagai contoh untuk menganalisis punca dan kaedah pembaikan kecacatan penguncian semak semula.
Pengunci semakan dua kali tidak mempunyai kesan dalam persekitaran berbilang benang persekitaran, disebabkan oleh Benang akan menukar pelaksanaan pada bila-bila masa Apabila arahan disusun semula, objek tidak dibuat seketika, mengakibatkan ralat panggilan program.
Sampel datang daripada Samate Juliet Test Suite untuk Java v1.3 (https://samate.nist.gov/SARD/testsuite. php ), nama fail sumber: CWE609_Double_Checked_Locking__Servlet_01.java.
Barisan kod di atas 23-38, atur cara mula-mula menentukan sama ada stringBad
adalah batal, jika Jika tidak, kembalikan objek String
terus, dengan itu mengelakkan sumber yang diperlukan untuk memasuki blok synchronized
. Gunakan kata kunci stringBad
untuk mengelak daripada mencipta objek synchronized
beberapa kali dalam persekitaran berbilang benang apabila String
adalah batal. Apabila kod sebenarnya dijalankan, ralat mungkin masih berlaku dalam kod di atas.
Untuk baris 33, penciptaan objek stringBad
dan operasi tugasan dilakukan dalam dua langkah. Tetapi JVM tidak menjamin susunan kedua-dua operasi ini. Apabila arahan disusun semula, JVM akan mula-mula menetapkan nilai yang menunjuk ke alamat memori, dan kemudian memulakan objek stringBad
. Jika terdapat dua utas pada masa ini, kedua-dua utas memasuki baris 27 pada masa yang sama. Thread 1 mula-mula memasuki blok synchronized
dan oleh kerana stringBad
adalah batal, ia melaksanakan baris 33. Apabila JVM menyusun semula arahan, JVM mula-mula memperuntukkan memori kosong bagi contoh dan menetapkannya kepada stringBad
, tetapi objek stringBad
masih belum digunakan, dan kemudian benang 1 meninggalkan blok synchronized
. Apabila benang 2 memasuki blok synchronized
, memandangkan stringBad
bukan batal pada masa ini, objek yang tidak segera dikembalikan secara langsung (hanya nilai alamat memori, objek sebenarnya tidak dimulakan). Apabila urutan 2 berikutnya memanggil program untuk beroperasi pada objek stringBad
, objek pada masa ini belum dimulakan, jadi ralat berlaku.
Gunakan 360 Code Guard untuk mengesan kod sampel di atas Anda boleh mengesan kecacatan "double check lock" dan tahap paparan adalah sederhana. Laporkan kecacatan pada baris 27 kod, seperti ditunjukkan dalam Rajah 1:
Rajah 1: Contoh pengesanan "Double Check Lock"
volatile
pada baris 23 untuk mengubah suai pembolehubah tunggal stringBad
. volatile
sebagai kata kunci arahan memastikan arahan tidak akan ditinggalkan kerana pengoptimuman pengkompil dan memerlukan bacaan terus nilai setiap kali. volatile
boleh menyelesaikan masalah ini secara semantik Perlu diingat bahawa larangan fungsi pengoptimuman penyusunan semula arahan volatile
telah dilaksanakan selepas Java 1.5, jadi versi sebelum 1.5 masih tidak selamat, walaupun ia digunakan volatile
. Kata kunci. Gunakan 360 Code Guard untuk mengesan kod yang dibaiki, dan anda boleh melihat bahawa kecacatan "double check lock" tidak lagi wujud. Seperti yang ditunjukkan dalam Rajah 2:
JVM akan melaksanakan pemulaan kelas semasa fasa pemulaan kelas (iaitu, selepas Kelas dimuatkan dan sebelum ia digunakan oleh utas). Semasa permulaan kelas pelaksanaan, JVM akan memperoleh kunci. Kunci ini boleh menyegerakkan permulaan kelas yang sama dengan berbilang benang.
Atas ialah kandungan terperinci Bagaimana untuk menganalisis penguncian semak semula dalam bahasa JAVA. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!