获取到的对象s是不同的,存在多线程安全问题。
只需使用同步就可以解决懒汉式的多线程安全问题。例如使用同步方法。
这样一来,每个线程来执行这个任务时,都将先判断Single.class这个对象标识的锁是否已经被其他线程持有。虽然解决了问题,但因为每个线程都额外地判断一次锁,导致效率有所下降。可以采用下面的双重判断来解决这个效率降低问题。
这样一来,当第一个线程执行这个任务时,将判断s==null
为true,于是执行同步代码块并持有锁,保证任务的原子性。而且,即使在最初判断s==null
后切换到其他线程了,也没有关系,因为总有一个线程会执行到同步代码块并持有锁,只要持有锁了就一定执行s= new Single()
,在这之后,所有的线程在第一阶段的"s==null"判断都为false,从而提高效率。其实,双重判断的同步懒汉式的判断次数和饿汉式的判断次数几乎相等。
最典型的死锁是僵局问题,A等B,B等A,谁都不释放,造成僵局,最后两个线程都无法执行下去。
例如下面的代码示例,sale1()中,obj锁需要持有this锁才能完成任务整体,而sale2()中,this锁需要持有obj锁才能完成任务整体。当两个线程都开始执行任务后,就开始产生死锁问题。
为了避免死锁,尽量不要在同步中嵌套同步,因为这样很容易造成死锁。