前提是在单容器下。听说方法四要加 volatile 才安全,为什么?或者其他方法也有什么不安全的请指正?package com.aa;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class Singleton {
private static Singleton singleton=null;
private static Lock lock=new ReentrantLock();
/*
* 方法一 lazy init
*/
public static Singleton getInstance1(){
lock.lock();
try{
if(singleton==null){
singleton=new Singleton();
}
}finally{
lock.unlock();
}
return singleton;
}
/*
* 方法二 lazy init
*/
public synchronized static Singleton getInstance2(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
/*
* 方法三
*/
private static Singleton singleton3=new Singleton();
public static Singleton getInstance3(){
return singleton3;
}
/*
* 方法四
*/
private volatile static Singleton singleton4;
public static Singleton getInstance4(){
if(singleton4==null){
synchronized (Singleton.class) {
if(singleton4==null){
singleton4=new Singleton();
}
}
}
return singleton4;
}
public static void main(String[] args) {
new Thread("threadA"){
public void run(){
Singleton.getInstance3();
}
}.start();
new Thread("threadB"){
public void run(){
Singleton.getInstance3();
}
}.start();
}
}
import java.util.concurrent.locks.ReentrantLock;public class Singleton {
private static Singleton singleton=null;
private static Lock lock=new ReentrantLock();
/*
* 方法一 lazy init
*/
public static Singleton getInstance1(){
lock.lock();
try{
if(singleton==null){
singleton=new Singleton();
}
}finally{
lock.unlock();
}
return singleton;
}
/*
* 方法二 lazy init
*/
public synchronized static Singleton getInstance2(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
/*
* 方法三
*/
private static Singleton singleton3=new Singleton();
public static Singleton getInstance3(){
return singleton3;
}
/*
* 方法四
*/
private volatile static Singleton singleton4;
public static Singleton getInstance4(){
if(singleton4==null){
synchronized (Singleton.class) {
if(singleton4==null){
singleton4=new Singleton();
}
}
}
return singleton4;
}
public static void main(String[] args) {
new Thread("threadA"){
public void run(){
Singleton.getInstance3();
}
}.start();
new Thread("threadB"){
public void run(){
Singleton.getInstance3();
}
}.start();
}
}
不能工作的基本原因在于,在java编译器中Singleton的初始化与singleton4变量的赋值顺序不可预料。
volatile的我也没有使用过,网上是这么说的“一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份”