Rumah >Java >javaTutorial >Bagaimana untuk menyelesaikan masalah keselamatan benang dalam corak singleton Java?

Bagaimana untuk menyelesaikan masalah keselamatan benang dalam corak singleton Java?

王林
王林ke hadapan
2023-05-09 19:28:061507semak imbas

    1 Faktor yang perlu dipertimbangkan apabila menggunakan multi-threading

    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

    2. Mod tunggal

    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

    1. Mod lapar

    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;
        }
    }

    2 mod tidak mencipta tika apabila kelas dimuatkan dan hanya menciptanya apabila ia digunakan buat kali pertama

    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:

    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

    Keputusan:

    Isu keselamatan utas berlaku apabila tika itu mula-mula dibuat

    3. Mod malas (diperbaiki menggunakan disegerakkan)

    Kami menggunakan pengubahsuaian yang disegerakkan, ????‍????️Kod adalah seperti berikut:

    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:

    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
    Keputusan:

    Walaupun ia selamat untuk benang, ia tidak cekap

    4 Mod Lazy (diperbaiki dengan menggunakan kunci semak dua kali)

    Buat perubahan berdasarkan kod di atas:

    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 lagi

    Analisis 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

    Bagaimana untuk menyelesaikan masalah keselamatan benang dalam corak singleton Java? Antara pembolehubah yang diubah suai meruap, CPU menggunakan protokol ketekalan cache untuk memastikan data memori utama terkini dibaca

    Konsistensi cache: Jika utas lain mengubah suai pembolehubah yang diubah suai secara meruap, pembolehubah dalam cache CPU akan ditetapkan semula tidak sah, untuk mengendalikan pembolehubah ini, anda mesti membacanya semula dari memori utama

    <.> 4. Isu pengembangan yang tidak menentu (faham)

    Jika tidak menentu tidak menjamin pesanan Adakah terdapat sebarang masalah dengan cara kunci semak dua kali ditulis?

    Objek baharu dibahagikan kepada 3 arahan mengikut tertib:

    (1) Peruntukkan ruang ingatan objek

    (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!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam