2012-10-17 29 views
4

分區是我創建的一個小類。我有數以千計的分區駐留在命名爲Partitions的ConcurrentDictionary中。序列化之前,我想鎖定一個特定的分區,做一些工作然後解鎖分區。鎖定ConcurrentDictionary的值

在此期間沒有其他線程應該能夠訪問該分區。由於我的類Partition是一個引用類型,我想知道是否可以像下面的代碼中那樣鎖定一個單獨的Partition對象?

在下面的鎖定期間,這會阻止來自ConcurrentDictionary分區中單個分區的其他線程嗎?

我不想使用類級鎖定對象進行鎖定。我的思考過程是多個線程應該能夠同時運行下面的代碼。他們只是不應該能夠訪問特定的分區,如果它已被鎖定......

private void serializePartition(int partNo) 
    { 
     Partition p; 

     //Get a reference to the partition, lock, and save it to disk. 
     lock (p = Partitions[partNo]) 
     { 
      using (var file = File.Create(dataPath + tableName + partNo + ".ppmi")) 
      { 
       Serializer.Serialize(file, p); 
      } 

      //decrement _CurrentRecordsInMemory by the size of the partition. 
      Interlocked.Add(ref _CurrentRecordsInMemory, p.Data.Count * -1); 

      //Clear the partitions data to free up memory and reset partition variables 
      p.Data = null; 
      p.OnDisk = true; 
      p.StartCount = 0; 
     } 
    } 
+0

另一個鎖,實際上阻止線程使用分區的那個鎖在哪裏? –

+0

我想這就是我所要求的。由於分區是通過引用傳遞的,因此上面的鎖是否允許所有其他線程在serializePartition執行時訪問該分區? –

+0

我是根據ConcurrentDictionary訪問線程安全,如果這是你問的。 –

回答

2

您當前的實現只阻止分區對象在功能代碼這一點。只要線程不再執行serializePartition(),另一個線程仍然可以訪問該Partition對象。看到你正在使用ConcurrentDictionary,它是線程安全的,所以不應該有問題。

+0

只是爲了澄清,上面的鎖是否保持所有其他線程在serializePartition執行時以任何方式訪問分區?例如,如果另一個線程試圖通過分區[partNo]或Partitions.TryGetValue獲得相同的PartNo,它是否會在serializePartition返回時鎖定分區? –

+0

是的,它會阻止所有其他線程訪問serializePartition函數中的分區對象。其他線程將在鎖定語句中等待,直到鎖定被釋放。 – HyperDev

+0

感謝您的澄清! –

0

我不明白爲什麼其他線程不能訪問分區如果他們也不使用分區對象的鎖。 我換句話說,任何其他線程做的:Partitions[partNo]能夠訪問partion 除非它也是這樣做的:

lock (p = Partitions[partNo]) 
{ 
    //DO SOM STUFF ONLY WHEN YOU GOT ACCESS TO THE LOCK 
} 

澄清:

的鎖將只保留其它線程出來誰也嘗試鎖定相同的對象。它不阻止不嘗試鎖定對象的線程的訪問。

要解決這種情況,您可以使用可能的事件來阻止其他線程訪問分區對象,並在開始序列化並重置它之前設置此事件,或者在處理對象時從ConcurrentDictionary中刪除對象並將其放入之後回來。恰恰適合您的需求。

相關問題