2017-04-26 61 views
-1

編輯:改變「單身」爲「單身」,因爲它不是一個真正的單身人士。當一個類的單個實例等待任務時會發生什麼?

假設您有一個DataAccess類作爲應用程序中的單個實例運行。這個使用MongoDB,但它可以應用於任何具有內部異步調用的任何東西。

public class DataAccess 
{ 
    private IMongoDatabase _database; 

    public DataAccess(IMongoClient client) 
    { 
     _database = client.GetDatabase("myDataBase"); 
    } 

    public virtual async Task<IEnumerable<User>> GetUsers() 
    { 
     var collection = _database.GetCollection<User>("users").Find("{}"); 
     return await collection.ToListAsync(); 
    } 
} 

DataAccess添加爲我的啓動類的ConfigureServices方法的「單」:

services.AddSingleton<DataAccess, DataAccess>(); 

,然後將其注入到控制器。

假設我有thread1調用DataAccess.GetUsers(),並且正在等待ToListAsync方法的結果。現在thread1在thread1等待時調用DataAccess.GetUsers()。怎麼了?

  • DataAccess的實例是否被thread1鎖定,因此thread2無法在thread1完成之前開始執行GetUsers方法?
  • DataAccess的實例是否可用並且thread2運行相同的collection.Find方法,而thread1也在運行它?
  • DataAccess的實例是否可用,但是thread2在運行到已經運行的ToListAsync方法時會進入睡眠狀態?
+5

對不起,但Singleton在哪裏?從我的代碼中,我可以根據需要多次調用DataAccess構造函數。 – taquion

+0

我現在就更新它。 DataAccess是由控制器調用的單例。 – Micteu

+0

除非給定的類型在其文檔中明確地提到它被設計爲從多個線程並行調用,並且如果這樣做會產生什麼行爲,假定它不是被設計爲從多個線程調用並且將表現爲如果你這樣做,會出乎意料和錯誤。 – Servy

回答

1

選項2:可用的單例和thread2運行相同的collection.Find方法,而thread1也運行它。

這就是爲什麼當你編寫一個單例時,你必須確保代碼是安全的並行運行或者以一種現代風格運行。通常這需要在資源的周圍放置一個lock,將其從選項2變爲選項1.

+0

感謝您滿足我的好奇心,而不是試圖讓我感到愚蠢,因爲我的措辭有點偏離。 – Micteu

相關問題