Rumah >Java >javaTutorial >Bagaimana untuk menyelesaikan masalah keselamatan benang dalam corak singleton Java?
Meningkatkan kecekapan: Menggunakan multi-threading adalah untuk membuat penggunaan sepenuhnya sumber CPU, meningkatkan kecekapan tugas
Keselamatan benang:Perkara paling asas tentang menggunakan multi-benang adalah untuk memastikan keselamatan benang
Jadi apabila kita mereka bentuk pelbagai -kod berbenang, kita mesti Meningkatkan kecekapan pelaksanaan tugas sebanyak mungkin sambil memastikan keselamatan benang
Oleh itu:
Penguncian berbutir halus: kod kurang terkunci, supaya kod lain boleh dilaksanakan secara serentak dan selari
Pertimbangkan keselamatan rangkaian:
Kod yang tidak mengendalikan pembolehubah kongsi tidak mempunyai isu keselamatan
Untuk membaca pembolehubah kongsi, gunakan volatile untuk mengubah suai pembolehubah
Tulis ke pembolehubah yang dikongsi , gunakan penguncian disegerakkan
Mod tunggal boleh memastikan bahawa terdapat hanya satu contoh kelas tertentu dalam program, dan bukan Cipta berbilang kejadian
Contohnya: DataSource (kumpulan sambungan data), pangkalan data hanya memerlukan satu objek kumpulan sambungan
Mod tunggal terbahagi kepada mod lapar dan mod malas
Mod lapar mencipta contoh apabila kelas dimuatkan
Kaedah ini selamat untuk benang (JVM menggunakan penguncian secara dalaman, iaitu berbilang benang Panggil kaedah statik, hanya satu benang bersaing untuk mengunci dan menyelesaikan penciptaan, hanya dilaksanakan sekali)
Kod pelaksanaan:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){ } public static Singleton getInstance(){ return instance; } }
Kod pelaksanaan:
public class Singleton { private static Singleton instance = null; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
Perhatikan perkara di atas. kod, di bawah satu utas Tiada isu keselamatan utas, tetapi adakah terdapat isu keselamatan dalam persekitaran berbilang benang?
Analisis:
Kami menggunakan pengubahsuaian yang disegerakkan, ????????️Kod adalah seperti berikut:Apabila tika tidak dibuat, jika berbilang rangkaian memanggil kaedah getInstance, berbilang kejadian boleh dibuat dan terdapat isu keselamatan Benang Tetapi sebaik sahaja kejadian dibuat, isu keselamatan rangkaian tidak akan berlaku apabila urutan seterusnya memanggil kaedah getInstance
Isu keselamatan utas berlaku apabila tika itu mula-mula dibuat
Keputusan:3. Mod malas (diperbaiki menggunakan disegerakkan)
public class Singleton { private static Singleton instance = null; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
Apakah masalah dengan melaksanakan keselamatan benang dengan cara ini?
Analisis:
Buat perubahan berdasarkan kod di atas:Kami menggunakan pengubahsuaian yang disegerakkan pada kaedah, iaitu, setiap kali kaedah dipanggil, kunci akan dipertandingkan, tetapi contoh hanya perlu dibuat sekali sahaja, iaitu, selepas mencipta contoh, memanggil kaedah ini masih perlu bersaing untuk kunci untuk melepaskan kunci
Walaupun ia selamat untuk benang, ia tidak cekap
Keputusan:4 Mod Lazy (diperbaiki dengan menggunakan kunci semak dua kali)
Gunakan dua kali jika pertimbangan untuk mengurangkan kekerapan penguncian persaingan
Gunakan tidak menentu untuk mengubah suai contoh
Kod pelaksanaan:public class Singleton { private static volatile Singleton instance = null; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance == null){ //外层的if判断:如果实例被创建直接return,不让线程再继续竞争锁 //在没有创建实例时,多个线程已经进入if判断了 //一个线程竞争到锁,其他线程阻塞等待 synchronized (Singleton.class) { //内层的if判断,目的是让竞争失败的锁如果再次竞争成功的话判断实例是否被创建,创建释放锁return,没有则创建 if(instance == null){ instance = new Singleton(); } } } return instance; } }
Penghuraian dua kali jika:
Luar jika penghakiman:
Contohnya hanya dibuat sekali. >Apabila contoh tidak dibuat, beberapa utas bersaing untuk kunci pada masa yang sama , hanya satu utas berjaya dalam pertandingan dan mencipta contoh, dan utas lain yang gagal dalam persaingan akan menyekat dan menunggu apabila utas pertama melepaskan kunci , utas yang gagal dalam persaingan ini akan terus bersaing, tetapi contoh telah dibuat, jadi anda perlu melakukan Penghakiman sekali lagiAnalisis lukisan, seperti yang ditunjukkan di bawah:
3. Prinsip yang tidak menentu
<.>
Volatile menjamin penglihatan di peringkat Java, tidak menentu adalah operasi bebas. serentak dan laksanakannya secara selari, yang hampir sama cekapnya dengan pelaksanaan tanpa kunci
Antara pembolehubah yang diubah suai meruap, CPU menggunakan protokol ketekalan cache untuk memastikan data memori utama terkini dibaca
<.> 4. Isu pengembangan yang tidak menentu (faham)(1) Peruntukkan ruang ingatan objekJika tidak menentu tidak menjamin pesanan Adakah terdapat sebarang masalah dengan cara kunci semak dua kali ditulis?
Objek baharu dibahagikan kepada 3 arahan mengikut tertib:
(2) Segerakan objek( 3) Urutan pelaksanaan biasa untuk memberikan nilai kepada pembolehubah
ialah (1)(2)(3) JVM boleh mengoptimumkan dan menyusun semula susunan kepada (1)(3). (2)
Hasil penyusunan semula ini mungkin selepas ruang ingatan diperuntukkan, tugasan selesai sebelum objek dibuat seketika
Selepas tugasan yang salah ini, instance==null tidak ditubuhkan, dan benang akan tahan Untuk contoh yang belum dibuat seketika, ralat akan berlaku apabila menggunakan sifat dan kaedahnya
Selepas menggunakan tidak menentu untuk memastikan keteraturan:
Benang tidak peduli apabila objek baharu dicipta (1 )(2)(3) Apakah susunannya? Contoh yang diperolehi oleh utas berikutnya telah dijadikan contoh
Dalam CPU, terdapat mekanisme penguncian tahap CPU berdasarkan operasi pembolehubah yang tidak menentu (ia jaminan (1)(2) (3) Selepas semua pelaksanaan, tulis semula ke memori utama, dan kemudian lakukan operasi benang lain pada pembolehubah)
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan masalah keselamatan benang dalam corak singleton Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!