c# 多线程单例模式_多线程(七):单例设计模式

单例模式:解决一个类再内存中只存在一个对象。共享对象。

想要保证对象唯一。

1。。。为了避免该类过多的创建对象,那么就私有构造方法

2。。。但是还要让其他程序可以访问该类,那么只好在本类中自定义一个对象,

3。。。为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式

c# 多线程单例模式_多线程(七):单例设计模式_第1张图片

我现在应该怎么访问。Single类中构造方法都私有化了。不能创建对象。那么只能通过get方法访问拿到对象了。那只好把get方法设置为静态的,然后用类去调用。那么问题又来了,get方法中有return s. get一旦静态了之后,静态方法是不能访问非静态成员变量的。那么也只好把s也静态了,然后也private了 ,然后也 final了。代码如下:

c# 多线程单例模式_多线程(七):单例设计模式_第2张图片

这种方法叫做饿汉式,是一种线程安全的单例设计模式。为什么叫饿汉式?因为一上来就建立了对象,相当于先吃,等不及了。很像饿了几天的人。


下来就是懒汉式的单例设计模式:

什么是懒汉式呢?就是对象式方法被调用时候,才初始化,也叫做对象的延迟加载。

c# 多线程单例模式_多线程(七):单例设计模式_第3张图片

看起来没问题。其实有很大的问题,在多线程的情况下,这个静态get方法有可能两个线程都进去了,都进了if判断,然后都挂了,然后又都醒了,就都new 了对象,这时候内存中,对象就不唯一了。有没有什么别的方法呢?

c# 多线程单例模式_多线程(七):单例设计模式_第4张图片

这样加锁,当A线程进来后,无论CPU切出去了,还是怎么的。B线程始终进不了这个get静态方法,如果当B线程能进来的时候,那就说明A线程已经new完对象已经出去了,此时B线程进来判断s就不等于null,所以就不能new对象了。但是这个给方法加锁效率很低,当线程进方法的时候,每次都要判断有没有锁。

那怎么办?改一下代码如下:

c# 多线程单例模式_多线程(七):单例设计模式_第5张图片

锁静态方法的对象是类名.class 考虑一下这个改动有问题没?这样的改动跟在方法上加锁没有任何区别啊。 还是一样的,效率太低,你只不过是把synchronized挪下来了。

再改一下:

c# 多线程单例模式_多线程(七):单例设计模式_第6张图片

第一次当A线程进来,判断s不等于null,然后进了锁,然后判断锁里面的if满足了,然后还没new对象的时候,突然挂了,cpu切出去了,切到了B线程 ,当B线程进来的时候,判断外面那个if也是满足的,然后想进锁,进不来,因为A在锁里面,此时CPU切到A线程的时候,A就new了对象。然后return s 当B线程执行的时候 锁里面的if 要判断s==null,因为A线程已经return s了 ,s自然就不等于null,B线程自然就不满足锁里面的if判断,自然也就new不了对象。当C线程进静态方法的时候,判断锁外面的if,一看A线程 return 了 s ,所以C线程判断锁外面的if的时候就不满足,那就更不用判断锁了,所以,以后进来的线程,因为锁外面的if都不满足,都进不来if,何谈判断锁呢。这样就降低了后续线程判断锁的次数。就提高了效率。

当然volatile也是必不可少的。修饰一下private volatile static Single s = null;

你可能感兴趣的:(c#,多线程单例模式)