Rumah Java javaTutorial 双重检查锁定和延迟初始化

双重检查锁定和延迟初始化

Nov 14, 2016 am 09:45 AM

双重检查锁定的由来

在Java程序中,有时需要推迟一些高开销的对象的初始化操作,并且只有在真正使用到这个对象的时候,才进行初始化,此时,就需要延迟初始化技术。

延迟初始化的正确实现是需要一些技巧的,否则容易出现问题,下面一一介绍。

方案1

public class UnsafeLazyInit{ 
private static Instance instance; 
 
  public static Instance getInstance(){ 
    if (instance == null){ 
         instance = new Instance(); 
     } 
     return instance; 
 } 
}
Salin selepas log masuk

这种做法的错误是很明显的,如果两个线程分别调用getInstance,由于对共享变量的访问没有做同步,很容易出现下面两种情况:

1.线程A和B都看到instance没有初始化,于是分别进行了初始化。

2.instance=new Instance操作被重排序,实际执行过程可能是:先分配内存,然后赋值给instance,最后再执行初始化。如果是这样的话,其他线程可能就会读取到尚未初始化完成的instance对象。

方案2

public class UnsafeLazyInit{ 
private static Instance instance; 
 
public static synchronized Instance getInstance(){ 
    if (instance == null){ 
         instance = new Instance(); 
     } 
     return instance; 
 } 
}
Salin selepas log masuk

这种做法的问题是很明显的,每一次读取instance都需要同步,可能会对性能产生较大的影响。

方案3

方案3是一个错误的双重检测加锁实现,看代码:

public class UnsafeLazyInit{ 
private static Instance instance; 
 
public static Instance getInstance(){ 
    if (instance == null){ 
         synchronized(UnsafeLazyInit.classs){ 
             if (instance == null){ 
                  instance = new Instance(); 
               } 
          } 
     } 
     return instance; 
  } 
}
Salin selepas log masuk

这种方案看似解决了上面两种方案都存在的问题,但是也是有问题的。

问题根源

instance = new Instance();

这一条语句在实际执行中,可能会被拆分程三条语句,如下:

memory = allocate(); 
ctorInstance(memory); //2 
instance = memory; //3
Salin selepas log masuk

根据重排序规则,后两条语句不存在数据依赖,因此是可以进行重排序的。

重排序之后,就意味着,instance域在被赋值了之后,指向的对象可能尚未初始化完成,而instance域是一个静态域,可以被其他线程读取到,那么其他线程就可以读取到尚未初始化完成的instance域。

基于volatile的解决方案

要解决这个办法,只需要禁止语句2和语句3进行重排序即可,因此可以使用volatile来修改instance就能做到了。

private volatile static Instance instance;

因为Volatile语义会禁止编译器将volatile写之前的操作重排序到volatile之后。

基于类初始化的解决方案

Java语言规范规定,对于每一个类或者接口C ,都有一个唯一的初始化锁LC与之对应,从C到LC的映射,由JVM实现。每个线程在读取一个类的信息时,如果此类尚未初始化,则尝试获取LC去初始化,如果获取失败则等待其他线程释放LC。如果能获取到LC,则要判断类的初始化状态,如果是位初始化,则要进行初始化。如果是正在初始化,则要等待其他线程初始化完成,如果是已经初始化,则直接使用此类对象。

public class InstanceFactory{ 
    private static class InstanceHolder{ 
        public static Instance = new Instance(); 
     } 
      
    public static Instance getInstance(){ 
        return InstanceHolder.instance; //这里将导致instance类被初始化 
    }     
}
Salin selepas log masuk

结论

字段延迟初始化降低了初始化类或者创建实例的开销,但是增加零访问被延迟促使化的字段的开销。在大部分时候,正常的初始化要优于延迟初始化。如果确实需要对实例字段使用线程安全的延迟初始化,请使用上面介绍的基于volatile的延迟初始化方案;如果确实需要对静态字段使用线程安全的延迟初始化,请使用上面基于类初始化方案的延迟初始化。


Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
2 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Repo: Cara menghidupkan semula rakan sepasukan
1 bulan yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Cara mendapatkan biji gergasi
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Rangka Kerja 4 JavaScript teratas pada tahun 2025: React, Angular, Vue, Svelte Rangka Kerja 4 JavaScript teratas pada tahun 2025: React, Angular, Vue, Svelte Mar 07, 2025 pm 06:09 PM

Artikel ini menganalisis empat kerangka JavaScript teratas (React, Angular, Vue, Svelte) pada tahun 2025, membandingkan prestasi, skalabilitas, dan prospek masa depan mereka. Walaupun semuanya kekal dominan kerana komuniti dan ekosistem yang kuat, popul mereka yang relatif

Spring Boot Snakeyaml 2.0 CVE-2022-1471 Isu Tetap Spring Boot Snakeyaml 2.0 CVE-2022-1471 Isu Tetap Mar 07, 2025 pm 05:52 PM

Artikel ini menangani kelemahan CVE-2022-1471 dalam Snakeyaml, kecacatan kritikal yang membolehkan pelaksanaan kod jauh. Ia memperincikan bagaimana peningkatan aplikasi boot musim bunga ke snakeyaml 1.33 atau lebih lama mengurangkan risiko ini, menekankan bahawa kemas kini ketergantungan

Bagaimanakah mekanisme kelas muatan Java berfungsi, termasuk kelas yang berbeza dan model delegasi mereka? Bagaimanakah mekanisme kelas muatan Java berfungsi, termasuk kelas yang berbeza dan model delegasi mereka? Mar 17, 2025 pm 05:35 PM

Kelas kelas Java melibatkan pemuatan, menghubungkan, dan memulakan kelas menggunakan sistem hierarki dengan bootstrap, lanjutan, dan pemuat kelas aplikasi. Model delegasi induk memastikan kelas teras dimuatkan dahulu, yang mempengaruhi LOA kelas tersuai

Bagaimanakah saya melaksanakan caching pelbagai peringkat dalam aplikasi java menggunakan perpustakaan seperti kafein atau cache jambu? Bagaimanakah saya melaksanakan caching pelbagai peringkat dalam aplikasi java menggunakan perpustakaan seperti kafein atau cache jambu? Mar 17, 2025 pm 05:44 PM

Artikel ini membincangkan pelaksanaan caching pelbagai peringkat di Java menggunakan kafein dan cache jambu untuk meningkatkan prestasi aplikasi. Ia meliputi persediaan, integrasi, dan faedah prestasi, bersama -sama dengan Pengurusan Dasar Konfigurasi dan Pengusiran PRA Terbaik

Node.js 20: Peningkatan Prestasi Utama dan Ciri -ciri Baru Node.js 20: Peningkatan Prestasi Utama dan Ciri -ciri Baru Mar 07, 2025 pm 06:12 PM

Node.js 20 dengan ketara meningkatkan prestasi melalui penambahbaikan enjin V8, terutamanya pengumpulan sampah yang lebih cepat dan I/O. Ciri -ciri baru termasuk sokongan webassembly yang lebih baik dan alat penyahpepijatan halus, meningkatkan produktiviti pemaju dan kelajuan aplikasi.

Iceberg: Masa Depan Jadual Data Tasik Iceberg: Masa Depan Jadual Data Tasik Mar 07, 2025 pm 06:31 PM

Iceberg, format meja terbuka untuk dataset analitik yang besar, meningkatkan prestasi data dan skalabiliti. Ia menangani batasan parket/orc melalui pengurusan metadata dalaman, membolehkan evolusi skema yang cekap, perjalanan masa, serentak w

Cara berkongsi data antara langkah -langkah dalam timun Cara berkongsi data antara langkah -langkah dalam timun Mar 07, 2025 pm 05:55 PM

Artikel ini meneroka kaedah untuk berkongsi data antara langkah -langkah timun, membandingkan konteks senario, pembolehubah global, lulus argumen, dan struktur data. Ia menekankan amalan terbaik untuk mengekalkan, termasuk penggunaan konteks ringkas, deskriptif

Bagaimanakah saya dapat melaksanakan teknik pengaturcaraan berfungsi di Java? Bagaimanakah saya dapat melaksanakan teknik pengaturcaraan berfungsi di Java? Mar 11, 2025 pm 05:51 PM

Artikel ini meneroka mengintegrasikan pengaturcaraan berfungsi ke dalam Java menggunakan ekspresi Lambda, API Streams, rujukan kaedah, dan pilihan. Ia menyoroti faedah seperti kebolehbacaan dan kebolehkerjaan kod yang lebih baik melalui kesimpulan dan kebolehubahan

See all articles