天天看点

创建懒汉式单例模式线程安全问题

一、在方法上通过synchronized加锁

[java] 纯文本查看 复制代码

?

1

2

3

4

5

6

7

8

9

<code>public</code> <code>class</code> <code>singleteexample {</code>

<code>    </code><code>private</code> <code>static</code> <code>singleteexample singleteexample;</code>

<code>[p=</code><code>30</code><code>,</code><code>2</code><code>, left]   </code><code>private</code> <code>singleteexample() {</code>

<code>    </code><code>}[/p][p=</code><code>30</code><code>,</code><code>2</code><code>, left]</code><code>public</code> <code>synchronized</code> <code>static</code> <code>singleteexample getinstance() {[/p][/size][/font][p=</code><code>30</code><code>,</code><code>2</code><code>, left][font=微软雅黑][size=</code><code>3</code><code>]       </code><code>if</code> <code>(singleteexample ==</code><code>null</code><code>) {</code>

<code>            </code><code>singleteexample =</code><code>new</code> <code>singleteexample();</code>

<code>        </code><code>}</code>

<code>        </code><code>return</code> <code>singleteexample;</code>

<code>    </code><code>}</code>

<code>}</code>

这种方法可以保证线程安全,但性能会非常差,特别是在并发情况下,当一个线程执行这个方法的时候,其他线程都会被阻塞。

二 在代码块上通过synchronized加锁

10

11

12

<code>public</code> <code>class</code> <code>singleteexample2 {</code>

<code>    </code><code>private</code> <code>static</code> <code>singleteexample2 singleteexample;</code>

<code>[p=</code><code>30</code><code>,</code><code>2</code><code>, left]   </code><code>private</code> <code>singleteexample2() {</code>

<code>    </code><code>}[/p][/size][/font][p=</code><code>30</code><code>,</code><code>2</code><code>, left][font=微软雅黑][size=</code><code>3</code><code>]   </code><code>public</code>  <code>static</code> <code>singleteexample2 getinstance() {</code>

<code>        </code><code>if</code> <code>(singleteexample ==</code><code>null</code><code>) {</code>

<code>            </code><code>synchronized</code> <code>(singleteexample2.</code><code>class</code><code>) {</code>

<code>                </code><code>singleteexample =</code><code>new</code> <code>singleteexample2();</code>

<code>            </code><code>}</code>

这种方法只有在singleteexample2对象为空时才会创建对象,细化了锁的力度,但在并发情况下,线程a,b同时执行这个方法,同时进行判断,都为空,a线程得到锁,初始化,

b线程等a线程释放锁后,b线程接着进行初始化,a  b两个线程得到的不是同一个对象。

三 双重检查

13

14

15

16

17

<code>public</code> <code>class</code> <code>singleteexample3 {</code>

<code>    </code><code>private</code> <code>static</code> <code>singleteexample3 singleteexample;</code>

<code>    </code><code>private</code> <code>singleteexample3() {</code>

<code>    </code><code>public</code> <code>static</code> <code>singleteexample3 getinstance() {</code>

<code>            </code><code>synchronized</code> <code>(singleteexample3.</code><code>class</code><code>) {</code>

<code>                </code><code>if</code> <code>(singleteexample ==</code><code>null</code><code>) {</code>

<code>                    </code><code>singleteexample =</code><code>new</code> <code>singleteexample3();</code>

<code>                </code><code>}</code>

b线程得到锁后初始化前仍会判断singleteexample3对象是否为空,这时singleteexample3对象已经初始化了,判断结果为false,b不会再次创建对象。

四 指令重排序

创建一个对象分为三步 1.分配内存空间 2.初始化对象 3.将内存空间的地址赋值给对象的引用。

其中2、3步执行时虚拟机是会重排序的。若a线程执行时jvm将2 3步重排序,那么此时对象的引用指向的内存空间仅仅只是一个地址,

这时候b线程进行第一次为空判断时,发现不为空,会将对象的引用返回。使用volatile关键字禁止jvm重排序。

<code>public</code> <code>class</code> <code>singleteexample4 {</code>

<code>    </code><code>private</code> <code>static</code> <code>volatile</code> <code>singleteexample4 singleteexample;[/size]</code>

<code>[p=</code><code>30</code><code>,</code><code>2</code><code>, left][size=</code><code>3</code><code>]   </code><code>private</code> <code>singleteexample4() {</code>

<code>    </code><code>}[/size][/p][p=</code><code>30</code><code>,</code><code>2</code><code>, left][size=</code><code>3</code><code>]   </code><code>public</code> <code>static</code> <code>singleteexample4 getinstance() {</code>

<code>            </code><code>synchronized</code> <code>(singleteexample4.</code><code>class</code><code>) {</code>

<code>                    </code><code>singleteexample =</code><code>new</code> <code>singleteexample4();</code>

<code> </code>

更多免费技术资料可关注:annalin1203