microsoft文檔:https://docs.microsoft.com/zh-cn/previous-versions/msp-n-p/ff650316(v=pandp.10)
參考:https://blog.csdn.net/yupu56/article/details/53668688
文檔:
lock:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/lock-statement
volatile:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/volatile#example
一. 基本
基礎(chǔ)代碼
public sealed class Singleton
{
private Singleton (){}
//使用volatile防止某線程讀取到instance不為null時弯院,instance引用的對象有可能還沒有完成初始化(另一線程中還沒有完成寫入操作)。
private static volatile Singleton instance;
private static object syncRoot = new Object();
public static Singleton Instance
{
get
{
//此處加一個if進行優(yōu)化泪掀。是因為只有在第一次創(chuàng)建對象的時候需要加鎖听绳。
if (instance == null)
{
lock (syncRoot) //如果沒有這個,不同的執(zhí)行線程同時進入Instance屬性方法,則可能會創(chuàng)建多個Singleton對象的實例
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
lock 關(guān)鍵字:
- 獲取給定對象的互斥 lock异赫。執(zhí)行語句塊椅挣,然后在釋放 lock头岔。
- 持有 lock 時,持有 lock 的線程可以再次獲取并釋放 lock鼠证。
- 阻止任何其他線程獲取 lock 并等待釋放 lock切油。
volatile關(guān)鍵字:
- 背景:
- 出于性能原因,編譯器名惩,運行時系統(tǒng)甚至硬件都可能對存儲器位置的讀取和寫入兩種操作重新排列澎胡,也就是說一個字段可以由多個線程同時執(zhí)行讀寫。
- 多個線程同時訪問一個變量娩鹉,CLR為了效率攻谁,允許每個線程進行本地緩存,這就導致了變量的不一致性弯予。
- 作用:申明了volatile的字段不進行讀寫操作重新排列的優(yōu)化戚宦。不允許線程進行本地緩存,每個線程的讀寫都是直接操作在共享內(nèi)存上锈嫩,這就保證了變量始終具有一致性受楼。
二. 單例模式父類
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DW
{
public class SingletonParent<T> where T : class, new()
{
protected SingletonParent() { }
private static volatile T instance;
private static readonly object syncRoot = new object();
public static T Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;
}
}
}
}
三. 關(guān)于繼承MonoBehaviour
- 加載腳本實例時會調(diào)用Awake
- 在初始化所有對象之后才調(diào)用Awake
- 所以,此時已經(jīng)被實例化呼寸,用this將當前實例對象給instance
private void Awake()
{
if(mMyInstance == null)
{
mMyInstance = this;
}
}