none
關於 Lock 的觀念問題 RRS feed

  • 問題

  • 我在系統中  有一個  global 的  HashTable
    自程式的兩個地方  分別會去  更新 刪除其中的值
    以下是 那兩段程式螞的大概
    lock(hashtable.synroot)
      {
         // 會有新增或者刪除Hashtable 的值
      }

    同時 另外一邊  有一段迴圈會去跑
    for(option in Hashtable)
      {
        //dosomething
      }

    以上兩段是同時在進行
    那在這邊  
    我會擔心  下面這一段跑迴圈時
    被上面的程式 lock 住  導至    Hashtable 有問題

    其實 我觀念 不是很清楚  可否  各位高手  
    教 我一下  lock  在這種  同時處理  要如何使用
    且運作的原理是如何  
        

       

    2009年12月16日 下午 03:31

解答

所有回覆

  • hi,
    先請問一下你是用二個thread去跑嗎?

    lock 關鍵字可保證有執行緒在關鍵區段時,絕對不會有任何其他執行緒同時也進入這個關鍵區段執行。如果其他執行緒嘗試進入已鎖定的程式碼,它將會等候、封鎖,直到該物件被釋出。
    請參考msdn
    http://msdn.microsoft.com/zh-tw/library/c5kehkcz.aspx


    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!
    • 已標示為解答 Lolota Lee 2009年12月22日 上午 06:43
    2009年12月16日 下午 04:35
  • 我在系統中  有一個  global 的  HashTable
    自程式的兩個地方  分別會去  更新 刪除其中的值
    以下是 那兩段程式螞的大概
    lock(hashtable.synroot)
      {
         // 會有新增或者刪除Hashtable 的值
      }

    同時 另外一邊  有一段迴圈會去跑
    for(option in Hashtable)
      {
        //dosomething
      }

    以上兩段是同時在進行
    那在這邊  
    我會擔心  下面這一段跑迴圈時
    被上面的程式 lock 住  導至    Hashtable 有問題

    其實 我觀念 不是很清楚  可否  各位高手  
    教 我一下  lock  在這種  同時處理  要如何使用
    且運作的原理是如何  
        

       


    是兩個執行緒
    我是想問   上面這樣的情況
    該如何 使用lock
    運作的道理在這個例子 該怎麼解識
    2009年12月16日 下午 04:43
  • 如果你在存取資料的時候,他在被lock的狀態,存取那邊就會等到你lock區塊做完之後才會繼續執行。

    使用lock要注意是否會發生死結哦。


    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!
    2009年12月16日 下午 04:53
  • 我在系統中  有一個  global 的  HashTable
    自程式的兩個地方  分別會去  更新 刪除其中的值
    以下是 那兩段程式螞的大概
    lock(hashtable.synroot)
      {
         // 會有新增或者刪除Hashtable 的值
      }

    同時 另外一邊  有一段迴圈會去跑
    for(option in Hashtable)
      {
        //dosomething
      }

    以上兩段是同時在進行
    那在這邊  
    我會擔心  下面這一段跑迴圈時
    被上面的程式 lock 住  導至    Hashtable 有問題

    其實 我觀念 不是很清楚  可否  各位高手  
    教 我一下  lock  在這種  同時處理  要如何使用
    且運作的原理是如何  
        

       


    向我這個例子  我只有lock 住一邊
    是否  在迴圈跑到一半  hashtable 的主控權會被下面那段thread 拿走
    是否應該兩邊都lock
    2009年12月16日 下午 05:02
  • lock的用法是鎖物件和程式區段,讓不同的THREAD不要一起跑同一段造成變數不正常,所以另外一段是不用鎖的。

    但是你提到的狀況是有可能發生的:跑到一半物件會被鎖到。

    通常的做法是如果有人正在使用該物件就把物件鎖起來,也就是你在讀的時候就不要讓其它THREAD去改到他。

    可以參考以下的程式範例:
    http://support.microsoft.com/default.aspx/kb/816161/zh-tw
    第一個:在多執行緒環境協助保護模組中的全域資料


    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!
    2009年12月16日 下午 05:14
  • lock 是一個程式碼區塊,
    兩個不同的 thread 同時執行到 lock 同一個 object 的程式碼區塊時,
    後 lock 的會等先 lock 的離開這個區塊後再往下執行,
    所以只 lock 一邊應該是沒有作用
    2009年12月17日 上午 04:05
  • HI,


    您可以考慮利用HashTable類別的Synchronized方法(http://msdn.microsoft.com/en-us/library/system.collections.hashtable.synchronized.aspx)創造一個可以被多執行緒同時使用的HashTable, 避免自行用lock來控制的困擾.

    • 已標示為解答 Lolota Lee 2009年12月22日 上午 06:43
    2009年12月17日 上午 05:51
  • HI,


    您可以考慮利用HashTable類別的Synchronized方法(http://msdn.microsoft.com/en-us/library/system.collections.hashtable.synchronized.aspx)創造一個可以被多執行緒同時使用的HashTable, 避免自行用lock來控制的困擾.


    哇 太感謝大家的解惑 我大概知道如何處理
    可是  我剛遇到一個  很奇怪的問題 
    例如:
      lock(myclass.hashtable)
       {
           hashtable m_t = myclass.hashtable;
          for(option m_i in m_t)
              {
                   .....
                  ....
              }
         }

    我已經lock住這個 hashtable啦 其它地方也有進行lock hashtable
    但  "有時"  會出現  在以上這段程式碼中的 try catch 中  說  "項目已經移動  集合變更 " 的exception
    又不會常常出現   是以上哪邊寫法有問題嘛

    大家再幫幫忙囉  感恩  趕案子中....

    2009年12月17日 下午 03:43
  • 不是這樣寫啦=  =
    你沒有去看我的給範例嘛

    是把hashtable弄成屬性,取存他之前先判斷是否有被lock。
    不然就像tihs大說的用別的方法建立
    http://msdn.microsoft.com/zh-tw/library/system.collections.hashtable.synchronized%28VS.80%29.aspx


    那個long number就是相當於你的hashtable
    public long Number   // the Number property
    {
    	get
    	{
    		//Acquire a read lock on the resource.
    		rwl.AcquireReaderLock(Timeout.Infinite);                
    		try
    		{
    			Console.WriteLine("Thread:{0} starts getting the Number", Thread.CurrentThread.GetHashCode());
    			Thread.Sleep(50);
    			Console.WriteLine("Thread:{0} got the Number", Thread.CurrentThread.GetHashCode());
    
    		}
    		finally
    		{
    			//Release the lock.
    			rwl.ReleaseReaderLock();
    		}
    		return myNumber;
    	}
    	set
    	{
    		//Acquire a write lock on the resource.
    		rwl.AcquireWriterLock(Timeout.Infinite);
    		try
    		{
    			Console.WriteLine("Thread: {0} start writing the Number", Thread.CurrentThread.GetHashCode());
    			Thread.Sleep(50);
    			myNumber = value;
    			Console.WriteLine("Thread: {0} written the Number", Thread.CurrentThread.GetHashCode());
    		}
    		finally
    		{
    			//Release the lock.
    			rwl.ReleaseWriterLock();
    		}
    	}
    }
    

    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!
    2009年12月18日 上午 01:46
  • 不是這樣寫啦=  =
    你沒有去看我的給範例嘛

    是把hashtable弄成屬性,取存他之前先判斷是否有被lock。
    不然就像tihs大說的用別的方法建立
    http://msdn.microsoft.com/zh-tw/library/system.collections.hashtable.synchronized%28VS.80%29.aspx


    那個long number就是相當於你的hashtable
    public long Number   // the Number property
    
    {
    
    	get
    
    	{
    
    		//Acquire a read lock on the resource.
    
    		rwl.AcquireReaderLock(Timeout.Infinite);                
    
    		try
    
    		{
    
    			Console.WriteLine("Thread:{0} starts getting the Number", Thread.CurrentThread.GetHashCode());
    
    			Thread.Sleep(50);
    
    			Console.WriteLine("Thread:{0} got the Number", Thread.CurrentThread.GetHashCode());
    
    
    
    		}
    
    		finally
    
    		{
    
    			//Release the lock.
    
    			rwl.ReleaseReaderLock();
    
    		}
    
    		return myNumber;
    
    	}
    
    	set
    
    	{
    
    		//Acquire a write lock on the resource.
    
    		rwl.AcquireWriterLock(Timeout.Infinite);
    
    		try
    
    		{
    
    			Console.WriteLine("Thread: {0} start writing the Number", Thread.CurrentThread.GetHashCode());
    
    			Thread.Sleep(50);
    
    			myNumber = value;
    
    			Console.WriteLine("Thread: {0} written the Number", Thread.CurrentThread.GetHashCode());
    
    		}
    
    		finally
    
    		{
    
    			//Release the lock.
    
    			rwl.ReleaseWriterLock();
    
    		}
    
    	}
    
    }
    
    
    
    

    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!

    拍謝  我比較笨 我想請問一下
    這樣  在 跑迴圈時 突然有其它執行緒更動資料
    所有有Lock 但  增加完不就釋放Lock 但 此時 若還在迴圈內
    不就  會有exception

    2009年12月22日 上午 08:28

  • 拍謝  我比較笨 我想請問一下
    這樣  在 跑迴圈時 突然有其它執行緒更動資料
    所有有Lock 但  增加完不就釋放Lock 但 此時 若還在迴圈內
    不就  會有exception


    Hashtable.SyncRoot:
    透過集合的列舉基本上並非安全的執行緒程序。即使集合經過同步化,其他的執行緒仍可修改該集合,使列舉值擲回例外狀況。如果要保證列舉過程的執行緒安全,您可以在整個列舉過程中鎖定集合 ,或攔截由其他執行緒的變更所造成的例外狀況。

    也就是說...
    你讀之前就先把他鎖掉,然後讀完再放掉,寫的時候也一樣,寫的時候就鎖掉,寫完再放掉
    Hashtable myCollection = new Hashtable();
      lock(myCollection.SyncRoot) {
      foreach (Object item in myCollection) {
      // Insert your code here.
      }
     }
    MSDN連結:http://msdn.microsoft.com/zh-tw/library/system.collections.hashtable.syncroot%28VS.80%29.aspx

    this大提供的連結裡面也有寫到這個範例...=_______=


    My Blog:http://www.dotblogs.com.tw/alonstar
    解決問題之後,別忘了回到論壇把正確回應標示成解答哦!
    2009年12月22日 上午 10:22