C# 線程使用

1.lock鎖定

 建立一個類,代碼如下:

View Code
class Person
{
private readonly int RunCount = 10000;
private int RunCountA = 0;//A方法執行的次數
private int RunCountB = 0;//B方法執行的次數
private int RunCountC = 0;//總共方法執行的次數
private bool IsRunA = true;
public void DoWorkA() {
Console.WriteLine("DoWorkA...");
while (true)
{
if (RunCountA == RunCount || RunCountB == RunCount)
{
Console.WriteLine("DoWorkA:RunCountA:{0} RunCountB:{1} RunCountC:{2}", RunCountA, RunCountB, RunCountC);
break;
}
//lock (o)
//{
if (IsRunA)
{
RunCountA++;
RunCountC++;
IsRunA = !IsRunA;
}
//}

}
}
public void DoWorkB()
{
Console.WriteLine("DoWorkB...");
while (true)
{
if (RunCountA == RunCount || RunCountB == RunCount)
{
Console.WriteLine("DoWorkB:RunCountA:{0} RunCountB:{1} RunCountC:{2}", RunCountA, RunCountB, RunCountC);
break;
}
//lock (o)
//{
if (!IsRunA)
{
RunCountB++;
RunCountC++;
IsRunA = !IsRunA;
}
//}

}
}

private object o=new object();
}

調用代碼如下:

     static void Main(string[] args)
{
Person p = new Person();
System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(p.DoWorkA));
System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(p.DoWorkB));
System.Threading.Thread t3 = new System.Threading.Thread(new System.Threading.ThreadStart(p.DoWorkB));
t3.Start();
System.Threading.Thread t4 = new System.Threading.Thread(new System.Threading.ThreadStart(p.DoWorkB));
t4.Start();
t1.Start();
t2.Start();
Console.ReadLine();
}

在沒有使用lock對象的時候,得出的結果如下:

可以看出。RunCountA!=RunCount ,RunCountC不等於RunCountA+RunCountB,這個就是對線程共享變量的問題。

下面加上lock鎖定,要鎖定,定義一個objct變量

再次執行代碼:

會得到我們期望的數值,介面如下:

2.使用mutex

 定義:private Mutex mutex = new Mutex();

 鎖定:mutex.WaitOne();從這裡開始的代碼變量是安全的。

  釋放:mutex.ReleaseMutex();

把lock 去掉,用這2個語句代替。也能達到上面的效果。

3.Monitor是一個靜態類,提供靜態方法。

首先:定義一個object 對象,必須是object對象,否則會出錯。

      if (Monitor.TryEnter(o))
{
Monitor.Enter(o);
if (!IsRunA)
{
RunCountB++;
RunCountC++;
IsRunA = !IsRunA;
}
Monitor.Exit(o);
}

Monitor.TryEnter(o) 是否能進入這塊區域

Monitor.Enter(o);鎖定區域

 Monitor.Exit(o);釋放區域

4.Interlocked 提供原子鎖定,也是提供靜態方法

其中usingResource為int ,必須定義為private  int usingResource = 0,因為第一次是從0開始。要和開始方法中的變量不同。

如果Interlocked.Exchange(ref usingResource, 1)是1則private  int usingResource = 0,否則private  int usingResource = 1

  if (0 == Interlocked.Exchange(ref usingResource, 1))進入鎖定區域

Interlocked.Exchange(ref usingResource, 0); 釋放鎖定區域

Interlocked.Increment(ref safeInstanceCount);原子遞增,相當於 safeInstanceCount++
Interlocked.Decrement(ref safeInstanceCount);原子遞減,相當於 safeInstanceCount--

5.WaitCallback使用,允许线程通过发信号互相通信

如:此计算的格式为:result = first term + second term + third term,其中每项都要求使用计算出的基数进行预计算和最终计算

此類,需要調用ThreadPool這個進行護理。

5.1 定義幾個處理方法

AutoResetEvent[] autoEvents
           autoEvents = new AutoResetEvent[]
        {
            new AutoResetEvent(false),
            new AutoResetEvent(false),
            new AutoResetEvent(false)
        };
初始狀態為運行狀態。
5.2 定義ManualResetEvent manualEvent;表示,是否能執行完這個線程,可以繼續執行下面的代碼
初始化為: manualEvent = new ManualResetEvent(false);
manualEvent.Reset();為線程結束,可以繼續下面的代碼
5.3使用ThreadPool線程池來執行線程
   ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateBase));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateFirstTerm));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateSecondTerm));
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateThirdTerm));
5.4對於每一個方法 autoEvents[0].Set();表示第二個方法結束,可以釋放信號。
manualEvent.Set();是第一個方法結束,進入manualEvent處理中。
最後在manualEvent.Reset();方法后,將得到的結果進行處理。
6.ThreadPool系統提供的線程池,托管线程池中的线程为后台线程,每个进程都有一个线程池。线程池的默认大小为每个可用处理器有 25 个线程。
使用 SetMaxThreads 方法可以更改线程池中的线程数。線程池中的線程,是自動執行的。
6.1ThreadPool.QueueUserWorkItem
将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。此方法,可以帶參數,可以傳遞給方法參數
 ThreadPool.QueueUserWorkItem(
                new WaitCallback(CalculateBase),"12");
7. LockCookie 单个编写器/多个阅读器语义的锁
7.1 ReaderWriterLock rwl = new ReaderWriterLock();定義鎖
7.2 rwl.AcquireReaderLock(timeOut);讀取鎖開始
rwl.ReleaseReaderLock();釋放讀取鎖。
7.3 LockCookie lc = rwl.UpgradeToWriterLock(timeOut);定義寫鎖
rwl.DowngradeFromWriterLock(ref lc);釋放寫鎖。







 


               





posted @ 2012-03-24 10:43  無限遐想  阅读(1116)  评论(0编辑  收藏  举报