天天看点

(49)静态同步函数的锁是Class对象,例子:懒汉式--在多线程中存在问题--同步解决

一、如果同步函数被静态修饰后,使用的锁是什么呢?

通过验证,发现使用的不是this.因为静态方法中也不可以定义this

静态进内存,内存中没有本类对象,但是一定个该类对应的字节码文件对象。

类名.class 该对象的类型为Class.

静态的同步方法,使用的锁是该方法所在类的字节码文件兑现,类名.class

二、懒汉式—-在多线程中存在安全问题

这个静态方法被run调用后,存在安全问题原因:

s是个共享数据,当一个线程执行到if(s==null)时,判为真时,cpu执行其他的程序去了,比如此时另一个线程,此时执行if(s==null),因为刚才的线程并没有创建对象,所以判断为真,这样就会创建两个对象,存在安全问题

将此函数改为同步函数,就可以解决这个问题。

class Single

{

private static Single s=null;

private Single(){}

public static synchronized Single getInstance(){

if(s==null)

s=new Single();

return s;

}

但是这样会使得多线程运行效率低,原因是加锁多个判断条件。

为什么在synchronized中也要写个if(s==null)呢?

举个栗子说明:

第一个线程在外层if判断成功后,进入同步块,判断内部的if,成立,此次CPU被剥夺,比如执行到第二个线程,同样判断外层的if,因为上同步块上着锁,进不了,隔一段时间,第一个线程得到cpu,继续执行,创建了对象,开锁。然后隔一段时间,第二个线程继续执行,进入共享区,然后if(s==null)判断失败,开锁,这就防止了创建对个对象。因为只有一个对象,所以以后的外层if (s==null)

都判断失败,因为已经有对象了,这样就摆脱了在多线程中使用同步方法、,每次都判断是否有锁,运行效率有所提高。

继续阅读