Unity 单例技巧 之 多线程时快速会单例“加锁”
1、Lock:
1)lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:
Object thisLock = new Object();
lock (thisLock)
{
// Critical code section
}
2)lock 确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
2、volatile:
1)volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。
2)volatile 修饰符通常用于由多个线程访问而不使用 lock 语句(C# 参考)语句对访问进行序列化的字段
3、本案例加锁特点:
1)Volatile 与 Lock 并用,双重保险;
2)双检查加锁模式。在lock之外和之内,我们做了instance是否为空的检查。这叫双检查。因为同步控制的时间太长了。双检查能够最高效地实现多线程安全的访问
1、打开Unity,新建一个空工程,然后Unity界面如下图

2、在工程中新建一个脚本,脚本可以命名为“SingletonLockTest”,具体如下图

3、选中“SingletonLockTest”脚本,双击脚本或者右键“Open C# Project”,具体如下图

4、在打开的“SingletonLockTest”脚本上进行代码编辑,首先设置一个静态单例变量,注意加上“volatile”修饰,然后设置一个静态锁对象,最后在单例属性中判断单例是否为空,若为空加锁,继续判断单例是否为空,为空则new个单例,具体代码及代码说明如下图

5、具体脚本代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SingletonLockTest : MonoBehaviour {
private static volatile SingletonLockTest instance;
private static object locker = new object();
public static SingletonLockTest Instance {
get {
if (instance == null) {
lock (locker) {
if (instance == null) {
instance = new SingletonLockTest();
}
}
}
return instance;
}
}
}
6、脚本编译正确后,回到Unity界面,在场景中新建一个“GameObject”,然后把脚本“SingletonLockTest”赋给“GameObject”,具体如下图

7、这样,就可以在多线程使用中保证一个单例不会被多次new的情况
8、到此,《Unity 单例技巧 之 可重用可自动挂载的单例基类》讲解结束,谢谢