posted on 2009-04-24 08:53 kevin-moon
前段時間仔細看過些關於多執行緒方面的資料,專案中用到執行緒的地方也不少,可是,當看了jeffrey的一篇關於鎖的文章後,發現自己雖然一直都在使用多執行緒,但是缺少了做多執行緒程式設計需要的思維!所以想從jeffrey的optex(鎖)入手,來談談我從其中體會的東西。
在net中,我們用的最多的鎖機制就是lock,用起來很簡單,短短幾行程式就可以實現,例如:
lock 's code
public class testthreading
}}其實我們也明白,lock並不是鎖,而是ms提供的乙個簡便式的寫法,真正實現的是monitor類中的enter和exit方法,既然提到了monitor類也就說下有個需要注意的地方:
pulse和pulseall方法,這兩個方法就是把鎖狀態將要改變的訊息通知給等待佇列中的執行緒,不過這時如果等待佇列中沒有執行緒,那麼該方法就會一直等待下去,直到有等待的執行緒進入佇列,也就是說該方法可能造成類試死鎖的情況出現。
上面的lock + 執行緒(thread和threadpool) = 多執行緒程式設計(n%)!?
對於該公式我曾經的n是80,現在是20。其中有很多東西影響我,讓我從80->20,下面的optex就是乙個入口點。
optex 's code
public sealed class optex : idisposable
public void dispose()
}public void enter()
// another thread has the optex, we need to wait for it
m_waiterlock.waitone();
// when waitone returns, this thread now has the optex
}public void exit()
thread.endcriticalregion();
}} 看完上面的**,讓我增加了兩點認識:
1、thread.begincriticalregion()和thread.endcriticalregion();
因為這段時間正好看了一本多執行緒程式設計的書,既然將上面方法認為是進入臨界區和退出臨界區,對於臨界區而言,進入該區的資料,在沒有退出之前,如果臨界區外的程式需要使用它,那麼就必須出於等待。所以覺得已經使用臨界區,為什麼還要使用semaphore?!
可是,ms只是取了個相同的名字,做的事情完全不同,上面兩個方法完全沒有臨界區的概念,它只是設定乙個區域(begin到end之間),表示該區域內發生執行緒中斷或未處理的異常會影響整個應用程式域。
2、m_waiters的作用
一開始以為在enter的時候,直接寫上:
m_waiterlock.waitone();
exit的時候,寫上:
m_waiterlock.release(1);
這樣就可以了。m_waiters有什麼意義?!
優化效能,semaphore是核心物件,我們都知道,要盡量少的進入核心模式,因為這是很消耗效能,所以盡量少的使用核心物件。m_waiters的意義就在這裡,如果只有乙個執行緒使用該鎖物件的時候,是不需要去獲取和釋放的。 ok,上述的東西都是鋪墊,鋪完了也就進入主題了!
多執行緒的思維
優化的optex
namespace threadconcurrent.lock
#endregion
///
/// 請求鎖
///
public void enter()}}
public void exit()
else
else
}thread.endcriticalregion();
}#region 原子化操作
///
/// 與操作
///
///
///
///
private static int32 interlockedand(ref int32 target, int32 with)
while (i != j);
return j;
}///
/// 或操作
///
///
///
///
private static int32 interlockedor(ref int32 target, int32 with)
while (i != j);
return j;
}#endregion
private static boolean ifthen(ref int32 val, int32 @if, int32 then)
private static boolean ifthen(ref int32 val, int32 @if, int32 then, out int32 prevval)
///
/// 釋放資源
///
public void dispose()}}
} 對於上面的這個**,我暈眩了好一段時間,不過當我真正理解的時候,從暈眩中學到了做多執行緒程式設計應該具備的思維方式。
首先從簡單的理解開始談,
1、原子化操作
對於interlocked類,曾經也知道,但是卻用的很少,不過從該**中知道,在多執行緒的程式設計中對共享資料的寫入操作,一定要達到原子性。至於如何做到這點,interlockedand和interlockedor做了很好的詮釋:
while迴圈的目的就是保證target值以最新的值做與操作,如果傳入的值在執行的過程被其他執行緒改變的話,那麼是不會退出該迴圈的,並會利用改變後的值重新做次與操作。
2、理解enter和exit
這兩個方法很難寫出來解釋,用圖是最清晰的。
曾經的暈眩:
1、enter方法中為什麼存在迴圈,為什麼不是執行完waitone就結束,必須m_lockstate等於c_isfree的時候才結束?
執行緒的執行並不完全按照先前排好的順序去執行,有時會發生一些特殊的情況來使改變執行緒的排程順序,所以就可能會出現上圖灰色部分的情況,則為了解決該可能發生的問題(概率很小)迴圈機制就出現了。
2、為什麼在waitone和release之前,除了增加和減少等待者外,還需要判斷m_lockstate是否改變(進入enter到執行waitone前的這段時間)?
一般性的思維:
該程式的思維:
這樣做的好處就是盡量少的操作核心物件,提高效能!
多執行緒程式設計雖然複雜,但是我覺得很有意思和挑戰性,而且隨著硬體的發展,多執行緒程式設計會更加重要,既然已經上路就讓我們走到盡頭!
談談多執行緒的思維方式
前段時間仔細看過些關於多執行緒方面的資料,專案中用到執行緒的地方也不少,可是,當看了jeffrey的一篇關於鎖的文章後,發現自己雖然一直都在使用多執行緒,但是缺少了做多執行緒程式設計需要的思維!所以想從jeffrey的optex 鎖 入手,來談談我從其中體會的東西。在net中,我們用的最多的鎖機制就...
談談多執行緒的思維方式
前段時間仔細看過些關於多執行緒方面的資料,專案中用到執行緒的地方也不少,可是,當看了jeffrey的一篇關於鎖的文章後,發現自己雖然一直都在使用多執行緒,但是缺少了做多執行緒程式設計需要的思維!所以想從jeffrey的optex 鎖 入手,來談談我從其中體會的東西。在net中,我們用的最多的鎖機制就...
談談多執行緒的思維方式
前段時間仔細看過些關於多執行緒方面的資料,專案中用到執行緒的地方也不少,可是,當看了jeffrey的一篇關於鎖的文章後,發現自己雖然一直都在使用多執行緒,但是缺少了做多執行緒程式設計需要的思維!所以想從jeffrey的optex 鎖 入手,來談談我從其中體會的東西。在net中,我們用的最多的鎖機制就...