一些概念了解
阻塞:函數返回結果之前,線程被掛起
非阻塞:函數執行完立即返回,不會阻塞線程
同步:函數沒有執行完不返回,線程被掛起;
異步:函數立即返回,結果通過事件或是信號通知調用者;
同步消息處理就好比linux中簡單的read/write操作,它們需要等待這操作成功才能返回;而異步處理機制就是類似於select/poll之類的多路復用IO操作,當所關注的消息被觸發時,由消息觸發機制通知觸發對消息的處理.
進程:當一個程序運行時,它就是一個進程,進程包括運行中的程序所使用到的內存和系統資源,同時一個進程可以包括多個線程
線程:線程是程序中的一個執行流,每個線程都有自己的專有寄存器(棧指針、程序計數器等),但代碼區是共享的,即不同的線程可以執行同樣的函數。
多線程:多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個並行執行的線程來完成各自的任務。時間片有CPU分配運行!
Thread主要方法:Strart(),Sleep(int),Abort(),Suspend(),Resume()
線程優先級:在C#應用程序中,用戶可以設定5個不同的優先級,由高到低分別是Highest,AboveNormal,Normal,BelowNormal,Lowest,在創建線程時如果不指定優先級,那麼系統默認為ThreadPriority.Normal。
線程同步(Framework中已經為我們提供了三個加鎖的機制,分別是Monitor類、Lock關鍵字和Mutex類。
):
a.C#提供了一個關鍵字lock,它可以把一段代碼定義為互斥段(critical section),互斥段在一個時刻內只允許一個線程進入執行,而其他線程必須等待。
在C#中,關鍵字lock定義如下:
lock(expression表達式) statement_block
b.Monitor主要用法
Monitor.Enter(obj);
(expression)
Monitor.Exit(obj);
c.Mutex用法
Mutex mutex = new Mutex();
mutex.WaitOne();
(expression)
mutex.ReleaseMutex();
舉個lock互斥例子(包括多線程使用和多線程優先權、同步使用):
[csharp]
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace TestThread
{
class Program
{
private static object lockObject = new object();
private static object lockObject2 = new object();
private static int iGetHBnum = 0;
private static int iPutHBnum = 0;
private static int count21 = 0;
private static int count22 = 0;
private static int count23 = 0;
private static int count11 = 0;
private static int count12 = 0;
static void Main(string[] args)
{
Console.WriteLine("主線程運行,線程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread chushi1 = new Thread(PutHB);
chushi1.Priority = ThreadPriority.AboveNormal;
chushi1.Name = "11";
chushi1.Start();
Thread chushi2 = new Thread(PutHB);
chushi2.Priority = ThreadPriority.Normal;
chushi2.Name = "12";
chushi2.Start();
Thread Consume21 = new Thread(GetHB);
Consume21.Priority = ThreadPriority.Normal;
Consume21.Name = "21";
Consume21.Start();
Thread Consume22 = new Thread(GetHB);
Consume22.Priority = ThreadPriority.Normal;
Consume22.Name = "22";
Consume22.Start();
Thread Consume23 = new Thread(GetHB);
Consume23.Priority = ThreadPriority.Normal;
Consume23.Name = "23";
Consume23.Start();
Console.ReadKey();
}
public static void PutHB()
{
string strID = Thread.CurrentThread.Name.ToString();
Console.WriteLine("{0}廚師開始制作漢堡,,,", strID);
while (true)
{
if (iPutHBnum >= 6)
{
Console.WriteLine("廚師{0},最多放6個漢堡,請讓銷售員取再放!", strID);
Thread.Sleep(1000);
}
else
{
if (iGetHBnum >= 70 ||count11 + count12 >= 70)
{
if (strID == "11")
{
Console.WriteLine("廚師{0},在貨架放共放{1}漢堡!", strID, count11);
}
else if (strID == "12")
{
Console.WriteLine("廚師{0},在貨架放共放{1}漢堡!", strID, count12);
}
break;
}
lock (lockObject)
{
iPutHBnum++;
}
if (strID == "11")
{
count11++;
Console.WriteLine("廚師{0},在貨架放已放{1}漢堡! 現在貨架有{2}漢堡!", strID,count11, iPutHBnum);
}
else if (strID == "12")
{
count12++;
Console.WriteLine("廚師{0},在貨架放已放{1}漢堡! 現在貨架有{2}漢堡!", strID, count12, iPutHBnum);
}
}
}
}
public static void GetHB()
{
string strID = Thread.CurrentThread.Name.ToString();
Console.WriteLine("{0}銷售員取漢堡,,,", strID);
while (true)
{
if (iPutHBnum <= 0)
{
Thread.Sleep(1000);
Console.WriteLine("{0}貨架台已0個漢堡,請等待廚師制作!", strID);
}
else
{
lock (lockObject2)
{
iGetHBnum++;
iPutHBnum--;
}
if (strID == "23")
{
count23++;
Console.WriteLine("23號銷售員已銷售---{0}!", count23);
Thread.Sleep(3000);
}
else if (strID == "22")
{
count22++;
Console.WriteLine("22號銷售員已銷售---{0}!", count22);
Thread.Sleep(2000);
}
else if (strID == "21")
{
count21++;
Console.WriteLine("21號銷售員已銷售---{0}!", count21);
Thread.Sleep(1000);
}
}
if (iGetHBnum >= 70)
{
Console.WriteLine("銷售完!");
if (strID == "23")
{
Console.WriteLine("23號銷售員銷售總數:{0}", count23);
}
else if (strID == "22")
{
Console.WriteLine("22號銷售員銷售總數:{0}", count22);
}
else if (strID == "21")
{
Console.WriteLine("21號銷售員銷售總數:{0}", count21);
}
break;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace TestThread
{
class Program
{
private static object lockObject = new object();
private static object lockObject2 = new object();
private static int iGetHBnum = 0;
private static int iPutHBnum = 0;
private static int count21 = 0;
private static int count22 = 0;
private static int count23 = 0;
private static int count11 = 0;
private static int count12 = 0;
static void Main(string[] args)
{
Console.WriteLine("主線程運行,線程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread chushi1 = new Thread(PutHB);
chushi1.Priority = ThreadPriority.AboveNormal;
chushi1.Name = "11";
chushi1.Start();
Thread chushi2 = new Thread(PutHB);
chushi2.Priority = ThreadPriority.Normal;
chushi2.Name = "12";
chushi2.Start();
Thread Consume21 = new Thread(GetHB);
Consume21.Priority = ThreadPriority.Normal;
Consume21.Name = "21";
Consume21.Start();
Thread Consume22 = new Thread(GetHB);
Consume22.Priority = ThreadPriority.Normal;
Consume22.Name = "22";
Consume22.Start();
Thread Consume23 = new Thread(GetHB);
Consume23.Priority = ThreadPriority.Normal;
Consume23.Name = "23";
Consume23.Start();
Console.ReadKey();
}
public static void PutHB()
{
string strID = Thread.CurrentThread.Name.ToString();
Console.WriteLine("{0}廚師開始制作漢堡,,,", strID);
while (true)
{
if (iPutHBnum >= 6)
{
Console.WriteLine("廚師{0},最多放6個漢堡,請讓銷售員取再放!", strID);
Thread.Sleep(1000);
}
else
{
if (iGetHBnum >= 70 ||count11 + count12 >= 70)
{
if (strID == "11")
{
Console.WriteLine("廚師{0},在貨架放共放{1}漢堡!", strID, count11);
}
else if (strID == "12")
{
Console.WriteLine("廚師{0},在貨架放共放{1}漢堡!", strID, count12);
}
break;
}
lock (lockObject)
{
iPutHBnum++;
}
if (strID == "11")
{
count11++;
Console.WriteLine("廚師{0},在貨架放已放{1}漢堡! 現在貨架有{2}漢堡!", strID,count11, iPutHBnum);
}
else if (strID == "12")
{
count12++;
Console.WriteLine("廚師{0},在貨架放已放{1}漢堡! 現在貨架有{2}漢堡!", strID, count12, iPutHBnum);
}
}
}
}
public static void GetHB()
{
string strID = Thread.CurrentThread.Name.ToString();
Console.WriteLine("{0}銷售員取漢堡,,,", strID);
while (true)
{
if (iPutHBnum <= 0)
{
Thread.Sleep(1000);
Console.WriteLine("{0}貨架台已0個漢堡,請等待廚師制作!", strID);
}
else
{
lock (lockObject2)
{
iGetHBnum++;
iPutHBnum--;
}
if (strID == "23")
{
count23++;
Console.WriteLine("23號銷售員已銷售---{0}!", count23);
Thread.Sleep(3000);
}
else if (strID == "22")
{
count22++;
Console.WriteLine("22號銷售員已銷售---{0}!", count22);
Thread.Sleep(2000);
}
else if (strID == "21")
{
count21++;
Console.WriteLine("21號銷售員已銷售---{0}!", count21);
Thread.Sleep(1000);
}
}
if (iGetHBnum >= 70)
{
Console.WriteLine("銷售完!");
if (strID == "23")
{
Console.WriteLine("23號銷售員銷售總數:{0}", count23);
}
else if (strID == "22")
{
Console.WriteLine("22號銷售員銷售總數:{0}", count22);
}
else if (strID == "21")
{
Console.WriteLine("21號銷售員銷售總數:{0}", count21);
}
break;
}
}
}
}
}
結果:
lock可以用Monitor,Mutex替代
Monitor.Enter(lockObject);
iPutHBnum++;
Monitor.Exit(lockObject);
或者
mutex1.WaitOne();
iPutHBnum++;
mutex1.ReleaseMutex();