日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

程序员面试题精选100题(45)-Singleton(C/C++/C#)

發布時間:2025/3/21 C# 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员面试题精选100题(45)-Singleton(C/C++/C#) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目:設計一個類,我們只能生成該類的一個實例。

分析:只能生成一個實例的類是實現了Singleton模式的類型。

由于設計模式在面向對象程序設計中起著舉足輕重的作用,在面試過程中很多公司都喜歡問一些與設計模式相關的問題。在常用的模式中,Singleton是唯一一個能夠用短短幾十行代碼完整實現的模式。因此,寫一個Singleton的類型是一個很常見的面試題。

事實上,要讓一個類型是能創建一個實例不是一件很難的事情。我們可以把該類型的構造函數設為private,這樣該類型的用戶就不能創建該類型的實例了。然后我們在給類型中創建一個靜態實例。當用戶需要該類型的實例時,我們就返回這個實例。基于這個思路,我們可以用C#寫出如下代碼:

????

// We can only get an instance of the class Singleton1. The instance// is created when class Singleton1 is referenced at the first timepublic sealed class Singleton1{private Singleton1(){}private static Singleton1 instance = new Singleton1();public static Singleton1 Instance{get{return instance;}}}

?

由于類Singleton1?的實例是一個靜態變量,因此它會在該類型的第一次引用的時候被創建,而不是第一次在調用Singleton1.get_Instance的時候被創建。如果我們此時并不需要該實例,那么我們就過早地初始化該實例,無論在內存空間還是CPU時間上都是一種浪費。

我們可以把上面的代碼稍作改動,就能實現在第一次調用Singleton_getInstance時候才會創建類型的唯一實例:

? ?

// We can only get an instance of the class Singleton2.// The instance is created when we need it explicitly.public sealed class Singleton2{private Singleton2(){}private static Singleton2 instance = null;public static Singleton2 Instance{get{if (instance == null)instance = new Singleton2();return instance;}}}

?

我們在單線程環境下只能得到類型Singleton2的一個實例,但在多線程環境下情況就可能不同了。設想如果兩個線程同時運行到語句if?(instance ==?null),而此時該實例的確沒有創建,那么兩個線程都會創建一個實例。此時,類型Singleton2就不在滿足模式Singleton的要求了。

為了保證在多線程環境下我們還是只能得到類型的一個實例,我們應該在判斷實例是否已經創建,以及在實例還沒有創建的時候創建一個實例的語句上加一個同步鎖。我們把Singleton2稍作修改就得到了如下代碼:

? ?

// We can only get an instance of the class Singleton3,// even when there are multiple threads which are trying// to get an instance concurrently.public sealed class Singleton3{private Singleton3(){}private static readonly object syncObj = new object();private static Singleton3 instance = null;public static Singleton3 Instance{get{lock (syncObj){if (instance == null)instance = new Singleton3();}return instance;}}}

?

說明一下,由于C/C++沒有為線程同步提供直接的支持。為了讓代碼顯得簡潔,而不是讓大量的代碼在實現同步鎖而偏離了實現Singleton的主題,本文的代碼用C#實現。

我們還是假設有兩個線程同時想創建一個實例。由于在一個時刻只能有一個線程能得到同步鎖。當第一個線程加上鎖時,第二個線程只能在等待。當第一個線程發現實例還沒有創建時,它創建出一個實例。接著第一個線程釋放同步鎖。此時第二個線程可以加上同步鎖,并運行接下來的代碼。由于此時實例已經被第一個線程創建出來了,第二個線程就不會重復創建實例了。于是保證了我們只能得到一個實例。

但是類型Singleton3還不是完美。由于我們每次調用Singleton3.get_Instance的時候,都會試圖加上一個同步鎖。由于加鎖是一個非常耗時的操作,在沒有必要的時候我們應該盡量避免這樣的操作。

實際上,我們只是在實例還沒有創建之前需要加鎖操作,以保證只有一個線程創建出實例。而當實例已經創建之后,我們已經不需要再做加鎖操作了。于是,我們可以把上述代碼再作進一步的改進:

??

// We can only get an instance of the class Singleton4,// even when there are multiple threads which are trying// to get an instance concurrently. When the instance has// been created, we don't need the lock any more.public sealed class Singleton4{private Singleton4(){}private static object syncObj = new object();private static Singleton4 instance = null;public static Singleton4 Instance{get{if (instance == null){lock (syncObj){if (instance == null)instance = new Singleton4();}}return instance;}}}

?

?我們只需要在最開始調用Singleton4_getInstance(可能來自一個線程,也可能來自多個線程)的時候需要加鎖。當實例已經創建之后,我們就不再需要作加鎖操作,從而在后續調用Singleton4_getInstance時性能得到提升。

關于第一種寫法的更多,請參考http://en.wikipedia.org/wiki/Double-checked_locking。站在面試的角度,本文的分析已經足夠應付。但如果想展示更多對多線程編程的理解,更深入地了解這個問題總是有益的。

本文已經收錄到《劍指Offer——名企面試官精講典型編程題》一書中,有改動,書中的分析講解更加詳細,增加了一種按需分配內存的方法。歡迎關注。

博主何海濤對本博客文章享有版權。網絡轉載請注明出處http://zhedahht.blog.163.com/。整理出版物請和作者聯系。

總結

以上是生活随笔為你收集整理的程序员面试题精选100题(45)-Singleton(C/C++/C#)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。