在一次面试过程中,面试官提到设计模式中单例模式,并要求我手写一个,于是我马上写出一个懒汉式-单例模式,如:
public class SingleDemo{
private static SingleDemo singleDemo = null;
private SingleDemo(){
}
public static SingleDemo getSingleDemo(){
if(singleDemo == null){
singleDemo = new SingleDemo();
}
return singleDemo;
}
}
她看了一下,问这个是线程安全的吗?于是我意识到她开始要将话题拉倒多线程方面了,很显然这并不是一个线程安全的代码。如果在高并发的情况下,很可能出现两个线程同时访问getSingleDemo方法,并new出两个SingleDemo实例。但是在最开始回答这是否是一个线程安全的时候,我回答可以通过线程同步来保证每个线程依次执行来保证线程依次访问getSingleDemo方法,然后我也不知道自己在说什么。但最会还是提出一个解决方案用synchronized修饰getSingleDemo方法,修改后代码如下:
public class SingleDemo{
private static SingleDemo singleDemo = null;
private SingleDemo(){
}
public static synchronized SingleDemo getSingleDemo(){
if(singleDemo == null){
singleDemo = new SingleDemo();
}
return singleDemo;
}
}
,也可以这样写:
public class SingleDemo{
private static SingleDemo singleDemo = null;
private SingleDemo(){
}
public static SingleDemo getSingleDemo(){
if(singleDemo == null){
synchronized(SingleDemo.class){
if(singleDemo == null){
singleDemo = new SingleDemo();
}
}
}
return singleDemo;
}
}
这中间有扯到synchronized修饰静态方法,非静态方法时各有什么区别,在这说明一下:
当synchronized修饰静态方法时,因为静态方法属于类方法,即在类加载时静态方法也同时加载,所以获得的锁是类的锁。
当synchronized修饰非静态方法时,因为非静态方法属于对象方法,所以获得的锁是对象的锁。
因为类锁和对象锁不同,他么不是互斥的。
最后提一下关于synchronized修饰this,object,*.class的区别。
synchronized(this)、synchronized(object)、synchronized(*.class)区别
下面单独对同步代码块的三种同步写法做一下区别:
1.synchronized(this)就死锁住当前this代表的对象,即对象锁,通常指某一个类的实例对象。
2.synchronized(object)属于对象锁,object本身就包含this的情况。
this指代的是当前同步块所在方法所在的类,当不需要引用别的类的时候。
object指代的是需要调用的类,引用了别的类,且需要处理多线程并发访问时,object指代的是被引用的类。如果没有引用别的类,则指代的就是同步块所在方法所在的类本身。
3.synchronized(*.class)的作用其实和synchronized static方法作用一样。Class锁对类其作用,也就是对类所有对象实例起作用。