程序地带

设计模式 - 18)单例模式


class STWindow
{
static Window win;
private STWindow() { }
public static Window GetInstance()
{
if (win == null || !win.IsVisible)
{
win = new Window();
win.Height = 200;
win.Width = 200;
}
return win;
}
}
class Singleton
{
static Singleton _singleton;
private Singleton() { }
public static Singleton GetInstance()
{
if (_singleton == null)
{
_singleton = new Singleton();
}
return _singleton;
}
}
1. 多线程同时创建实例问题

多个线程同时访问 Singleton 的 GetInstance() 方法,可能会造成创建多个实例;
比如 A 先进入后在准备实例化 Singleton 的过程中,B 也进入了,这时 _singleton 还是为 null,然后 B 也去实例化 Singleton 了。


class Singleton
{
static Singleton _singleton;
private Singleton() { }
public static Singleton GetInstance()
{
if (_singleton == null)
{
Console.WriteLine("实例化一个 Singleton");
_singleton = new Singleton();
}
Console.WriteLine("返回一个 Singleton");
return _singleton;
}
}
System.Threading.Thread a = new System.Threading.Thread(() =>
{
Singleton.GetInstance();
});
System.Threading.Thread b = new System.Threading.Thread(() =>
{
Singleton.GetInstance();
});
System.Threading.Thread c = new System.Threading.Thread(() =>
{
Singleton.GetInstance();
});
a.Start();
b.Start();
c.Start();
实例化一个 Singleton
实例化一个 Singleton
返回一个 Singleton
返回一个 Singleton
返回一个 Singleton

我们通过加个锁来解决这个问题。


public static readonly object syncRoot = new object();
public static Singleton GetInstance()
{
lock (syncRoot)
{
if (_singleton == null)
{
Console.WriteLine("实例化一个 Singleton");
_singleton = new Singleton();
}
}
Console.WriteLine("返回一个 Singleton");
return _singleton;
}
实例化一个 Singleton
返回一个 Singleton
返回一个 Singleton
线程 0x1a08 已退出,返回值为 0 (0x0)。
返回一个 Singleton
线程 0x45b4 已退出,返回值为 0 (0x0)。
线程 0x5a04 已退出,返回值为 0 (0x0)。
2. 每次实例都要锁的性能问题

使用双重锁定,只有未实例化时才锁,锁完判断是否还未实例化。


public static Singleton GetInstance()
{
if (_singleton == null)
{
lock (syncRoot)
{
if (_singleton == null)
{
_singleton = new Singleton();
}
}
}
return _singleton;
}
3.饿汉式单例
class Singleton
{
static readonly Singleton _instance = new Singleton();
private Singleton() { }
public static Singleton GetInstance()
{
return _instance;
}
}

这种静态初始化的方式是自己被加载时就将自己实例化,因此被称为饿汉式单例;
而第一次被引用时才将自己实例化的方式被称为懒汉式单例。C# 中饿汉式已足够满足。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/MichaelLoveSna/p/14199110.html

随机推荐

python变量和常量_000-Python常量与变量

python常量与变量昨天的文章虽然有插图,但是一个都没有显示出来,估计是天气太热,不愿意露面的缘故吧。这些都不是事,暂且不表,今...

weixin_39550410 阅读(913)

python变量和常量_5、python的变量和常量

今天看看python的变量和常量,这是python中最基本的两个概念。首先先说一下解释器执行Python的过程:  python3C: est.py1.启动python解...

weixin_39928461 阅读(119)

Linux-信号量互斥

Linux-信号量互斥1.消费者生产者问题通过创建两个线程,一个代表生产者,另一个代表消费者,申请一段固定大小的内存区域表示缓冲区,向缓冲区末尾...

Seldon1224 阅读(915)

F - 数据结构实验之数组二:稀疏矩阵

Description对于一个n*n的稀疏矩阵M(1<=n<=1000),采用三元组顺序表存储表示,查找从键盘输入的某个非零数据是否在稀疏矩阵中...

男孩lim 阅读(517)