自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C# Singleton的使用及優(yōu)缺點(diǎn)探討

開發(fā) 后端
本文簡單介紹了C# Singleton的使用,提供了一個實(shí)例,并分析了優(yōu)缺點(diǎn)若干。盡管 Singleton 是一種相對簡單的模式,但是存在與具體實(shí)現(xiàn)有關(guān)的不同權(quán)衡因素和選項。

您要在 C# 中構(gòu)建應(yīng)用程序。您需要只有一個實(shí)例的類,并且需要提供一個用于訪問實(shí)例的全局訪問點(diǎn)。您希望確保您的解決方案高效,并且能夠利用 Microsoft? .NET 公共語言運(yùn)行庫功能。您可能還希望確保解決方案是線程安全的。

C# Singleton實(shí)現(xiàn)策略

盡管 Singleton 是一種相對簡單的模式,但是存在與具體實(shí)現(xiàn)有關(guān)的不同權(quán)衡因素和選項。下面是一組實(shí)現(xiàn)策略,及其優(yōu)缺點(diǎn)的討論。

C# Singleton

Singleton 設(shè)計模式的下列實(shí)現(xiàn)采用了 Design Patterns: Elements of Reusable Object-Oriented Software [Gamma95] 中所描述的解決方案,但對它進(jìn)行了修改,以便利用 C# 中可用的語言功能,如屬性:

  1. using System;   
  2. public class Singleton   
  3. {   
  4.    private static Singleton instance;   
  5.    private Singleton() {}   
  6.    public static Singleton Instance   
  7.    {   
  8.       get    
  9.       {   
  10.          if (instance == null)   
  11.          {   
  12.             instance = new Singleton();   
  13.          }   
  14.          return instance;   
  15.       }   
  16.    }   
  17. }   

該實(shí)現(xiàn)主要有兩個優(yōu)點(diǎn):

由于實(shí)例是在 Instance 屬性方法內(nèi)部創(chuàng)建的,因此類可以使用附加功能(例如,對子類進(jìn)行實(shí)例化),即使它可能引入不想要的依賴性。

直到對象要求產(chǎn)生一個實(shí)例才執(zhí)行實(shí)例化;這種方法稱為"懶實(shí)例化"。懶實(shí)例化避免了在應(yīng)用程序啟動時實(shí)例化不必要的 singleton。

但是,這種實(shí)現(xiàn)的主要缺點(diǎn)是在多線程環(huán)境下它是不安全的。如果執(zhí)行過程的不同線程同時進(jìn)入 Instance 屬性方法,那么可能會創(chuàng)建多個 Singleton 對象實(shí)例。每個線程都會執(zhí)行下列語句,并決定必須創(chuàng)建新的實(shí)例:

  1. if (instance == null)   

解決此問題的方法有很多。一種方法是使用被稱為 Double-Check Locking [Lea99] 的技術(shù)。而 C# 與公共語言運(yùn)行庫也提供了一種"靜態(tài)初始化"方法,這種方法不需要開發(fā)人員顯式地編寫線程安全代碼,即可解決這些問題。

C# Singleton:靜態(tài)初始化

避免使用靜態(tài)初始化的原因之一是,C++ 規(guī)范在靜態(tài)變量的初始化順序方面留下了一些多義性。幸運(yùn)的是,.NET Framework 通過其變量初始化處理方法解決了這種多義性:

  1. public sealed class Singleton   
  2. {   
  3.    private static readonly Singleton instance = new Singleton();   
  4.    private Singleton(){}   
  5.    public static Singleton Instance   
  6.    {   
  7.       get    
  8.       {   
  9.          return instance;    
  10.       }   
  11.    }   
  12. }   

在此策略中,將在***次引用類的任何成員時創(chuàng)建實(shí)例。公共語言運(yùn)行庫負(fù)責(zé)處理變量初始化。該類標(biāo)記為 sealed 以阻止發(fā)生派生,而派生可能會增加實(shí)例。有關(guān)將類標(biāo)記為 sealed 的利與弊的討論,請參閱 [Sells03]。此外,變量標(biāo)記為 readonly,這意味著只能在靜態(tài)初始化期間(此處顯示的示例)或在類構(gòu)造函數(shù)中分配變量。

該實(shí)現(xiàn)與前面的示例類似,不同之處在于它依賴公共語言運(yùn)行庫來初始化變量。它仍然可以用來解決 Singleton 模式試圖解決的兩個基本問題:全局訪問和實(shí)例化控制。公共靜態(tài)屬性為訪問實(shí)例提供了一個全局訪問點(diǎn)。此外,由于構(gòu)造函數(shù)是私有的,因此不能在類本身以外實(shí)例化 Singleton 類;因此,變量引用的是可以在系統(tǒng)中存在的唯一的實(shí)例。

由于 Singleton 實(shí)例被私有靜態(tài)成員變量引用,因此在類***被對 Instance 屬性的調(diào)用所引用之前,不會發(fā)生實(shí)例化。因此,與 Design Patterns 形式的 Singleton 一樣,該解決方案實(shí)現(xiàn)了懶實(shí)例化屬性的一種形式。

這種方法唯一的潛在缺點(diǎn)是,您對實(shí)例化機(jī)制的控制權(quán)較少。在 Design Patterns 形式中,您能夠在實(shí)例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)。由于在此解決方案中由 .NET Framework 負(fù)責(zé)執(zhí)行初始化,因此您沒有這些選項。在大多數(shù)情況下,靜態(tài)初始化是在 .NET 中實(shí)現(xiàn) Singleton 的***方法。

多線程 Singleton

靜態(tài)初始化適合于大多數(shù)情形。如果您的應(yīng)用程序必須延遲實(shí)例化、在實(shí)例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)、并且工作在多線程環(huán)境中,那么您需要另一種解決方案。但是,在一些情況下,您無法像在"靜態(tài)初始化"示例中那樣依賴公共語言運(yùn)行庫來確保線程的安全性。在這種情況下,必須使用特定的語言功能來確保在存在多線程的情況下僅創(chuàng)建一個對象實(shí)例。更常見的解決方案之一是使用 Double-Check Locking [Lea99] 技術(shù)來阻止不同的線程同時創(chuàng)建 singleton 的新實(shí)例。

注意:公共語言運(yùn)行庫解決了在其他環(huán)境中常見的、與使用 Double-Check Locking 有關(guān)的問題。

下面的實(shí)現(xiàn)僅允許一個線程在尚未創(chuàng)建 Singleton 實(shí)例的情況下進(jìn)入關(guān)鍵區(qū)域(該區(qū)域由 lock 塊標(biāo)識)。

  1. using System;   
  2. public sealed class Singleton   
  3. {   
  4.    private static volatile Singleton instance;   
  5.    private static object syncRoot = new Object();   
  6.    private Singleton() {}   
  7.    public static Singleton Instance   
  8.    {   
  9.       get    
  10.       {   
  11.          if (instance == null)    
  12.          {   
  13.             lock (syncRoot)    
  14.             {   
  15.                if (instance == null)    
  16.                   instance = new Singleton();   
  17.             }   
  18.          }   
  19.          return instance;   
  20.       }   
  21.    }   
  22. }   

此方法確保了僅在需要實(shí)例時才會創(chuàng)建僅一個實(shí)例。此外,變量被聲明為 volatile,以確保只有在實(shí)例變量分配完成后才能訪問實(shí)例變量。***,此方法使用 syncRoot 實(shí)例來進(jìn)行鎖定(而不是鎖定類型本身),以避免發(fā)生死鎖。

此 double-check locking 方法解決了線程并發(fā)問題,同時避免在每個 Instance 屬性方法的調(diào)用中都出現(xiàn)獨(dú)占鎖定。它還允許您將實(shí)例化延遲到***次訪問對象時發(fā)生。實(shí)際上,應(yīng)用程序很少需要這種類型的實(shí)現(xiàn)。大多數(shù)情況下,靜態(tài)初始化方法已經(jīng)夠用。

C# Singleton優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

由于 .NET Framework 顯式地指定靜態(tài)變量初始化如何以及何時發(fā)生,因此靜態(tài)初始化方法是可能的。

列的前面的"多線程 Singleton"中所描述的 Double-Check Locking 技術(shù)已在公共語言運(yùn)行庫中正確實(shí)現(xiàn)。

缺點(diǎn)

如果您的多線程應(yīng)用程序需要進(jìn)行顯式初始化,那么必須采取措施以避免線程問題。

【編輯推薦】

  1. 淺析C#擴(kuò)展方法
  2. 簡單介紹C#預(yù)處理
  3. 學(xué)習(xí)C#無詞尾符號經(jīng)驗(yàn)談
  4. C#調(diào)用QuickTest自動化
  5. 詳解C#正規(guī)表達(dá)式
責(zé)任編輯:yangsai 來源: MSDN
相關(guān)推薦

2009-08-31 16:12:02

C#使用Singlet

2023-09-04 10:55:17

2009-09-04 15:53:42

C#內(nèi)存流

2009-09-02 16:23:27

C# Singleto

2009-08-25 18:04:30

C#實(shí)現(xiàn)Singlet

2009-08-31 15:48:02

C# Singleto

2011-08-09 09:49:23

存儲過程SQL語句數(shù)據(jù)庫

2012-05-03 09:58:19

VLANVLAN劃分

2017-10-23 13:20:37

2010-11-11 17:15:13

SQL Server視

2014-05-12 09:26:08

2010-08-27 09:45:49

CSS Sprites

2013-08-06 13:58:27

2019-05-28 15:20:17

2019-10-10 17:22:07

多云CIO多云策略

2024-05-23 16:56:58

2010-08-31 14:49:57

CSS居中

2010-09-02 09:59:52

CSS SpritesCSS

2018-12-11 10:59:35

Tomcat NginxApache

2009-09-11 12:50:34

Scope屬性
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號