2012年7月20日 星期五

關於互斥鎖

20110724046.jpg
由於最近使用Parallel for的平行化迴圈來運算

debug了一陣子都找不出問題所在

最後才知道遇上了critical section的問題


搜尋了一下C#提供了三種方法

Monitor,Mutex,和Semaphor
(可參閱此網誌的介紹)

其中最常見的方法就是Monitor的方法

而最簡易的方式就是使用lock指令
(lock就是實作Monitor的方法)

msdn lock方法

但lock卻有許多能力上的限制

看似簡單卻有許多小陷阱

可參考此網誌

介紹的蠻詳細的


在目前處理影像的部分由於Multi-Threading(多執行緒)跟非同步的關係

需要對同一個物件(影像)做存取

最簡單,又不會有問題的方式

就是自行宣告一個private 的物件作為lock的instance,如下:
(最好還是唯讀)

private Readonly Object _ThisLock = new Object();
private Bitmap _Frame;
...
lock (this._ThisLock)
{
//存取 _Frame 的 Critical code section.
}
...

如果有外部程式需要存取到此影像物件_Frame的話

就必須提供此物件的public的屬性讓外部程式參考使用
(通常不應該由外部程式來控制互斥鎖,應該在內部做掉)

public Bitmap Frame
{
    get
    {
        Bitmap bmp=null;
        lock(this._ThisLock)
        {
           bmp=this._Frame.clone() as Bitmap;
        }
        return bmp;
    }
}

這樣就可以達到外部程式取得此物件時的安全性

但是內部程式每次在控制_Frame的時候都要寫一次lock實在很麻煩

所以可以將Frame加入set的功能

public Bitmap Frame
{
    get
    {
        Bitmap bmp=null;
        lock(this._ThisLock)
        {
           bmp=this._Frame.clone() as Bitmap;
        }
        return bmp;
    }
    private set
    {
        lock(this._ThisLock)
        {
           if(this._Frame!=null) this._Frame.Dispose();
           this._Frame=value;
        }    
    }
}
由於_Frame只可由內部做設定

所以使用private set的方式來處理

避免外部程式來設定_Frame

這樣以後內部程式在做_Frame存取時就直接使用Frame

既可達到封裝效果(其實只是偷懶...),又完成thread save的存取

當然這只是簡單的存取機制

如果需要對_Frame做比較複雜的存取

就還是要自己寫了互斥鎖了!!

沒有留言:

張貼留言