--------------------------------------------------------------------------------
標題: 一讀一寫情況下,無鎖隊列如何實現?
作者: 葉飛虎
日期: 2009.03.09
--------------------------------------------------------------------------------
一讀一寫情況下,無鎖隊列如何實現?其實并不難,先說說一讀一寫無鎖隊列的實際應
用吧。讀寫隊列最大的應用是:一個線程收到事件或消息后直接加入到隊列,而處理線程讀
取隊列中的事件或消息,并加以處理。在這個模式中,有一個線程負責寫,多個處理線程讀
自己的隊列并處理。雖然看起來象是一寫多讀,其實不然,針對某一事件隊列而言,只有一
個線程是寫一個線程是讀。
此示例可以封裝成一個Queue類,在KYLib中有TKYQueue類,其實現原理相同。代碼示例
如下:
1 // 鏈接數據項結構
2 typedef struct TLinkItem
3 {
4 void* Data;
5 TLinkItem* Next;
6 } *PLinkItem;
7
8 TLinkItem* FLinkHead; // 隊列頭
9 TLinkItem* FLinkTail; // 隊列尾
10
11 // 初始化隊列
12 void InitQueue()
13 {
14 // 分配隊列頭項
15 FLinkTail = NULL;
16 FLinkHead = new TLinkItem;
17
18 // 保證 Head 和 Tail 非空, 是一個線程讀一個線程寫的關鍵!
19 if (FLinkHead != NULL)
20 {
21 // 初始化隊列頭
22 FLinkHead->Data = NULL;
23 FLinkHead->Next = NULL;
24 FLinkTail = FLinkHead;
25 }
26 else
27 throw;
28 }
29
30 // 加入
31 bool Push(void* AData)
32 {
33 // 初始化
34 bool result = false;
35 TLinkItem* pItem = new TLinkItem;
36
37 // 加入隊列
38 if (pItem != NULL)
39 {
40 // 寫值
41 pItem->Data = AData;
42 pItem->Next = NULL;
43
44 // 加到末尾
45 FLinkTail->Next = pItem;
46 FLinkTail = pItem;
47
48 // 返回結果
49 result = true;
50 }
51
52 // 返回結果
53 return result;
54 }
55
56 // 取出
57 void* Pop()
58 {
59 // 初始化
60 void* result = NULL;
61
62 // 讀取項
63 if (FLinkHead->Next != NULL)
64 {
65 // 取值
66 TLinkItem* pItem = FLinkHead;
67 FLinkHead = FLinkHead->Next;
68 result = FLinkHead->Data;
69
70 // 釋放項
71 delete pItem;
72 }
73
74 // 返回結果
75 return result;
76 }
77
2 typedef struct TLinkItem
3 {
4 void* Data;
5 TLinkItem* Next;
6 } *PLinkItem;
7
8 TLinkItem* FLinkHead; // 隊列頭
9 TLinkItem* FLinkTail; // 隊列尾
10
11 // 初始化隊列
12 void InitQueue()
13 {
14 // 分配隊列頭項
15 FLinkTail = NULL;
16 FLinkHead = new TLinkItem;
17
18 // 保證 Head 和 Tail 非空, 是一個線程讀一個線程寫的關鍵!
19 if (FLinkHead != NULL)
20 {
21 // 初始化隊列頭
22 FLinkHead->Data = NULL;
23 FLinkHead->Next = NULL;
24 FLinkTail = FLinkHead;
25 }
26 else
27 throw;
28 }
29
30 // 加入
31 bool Push(void* AData)
32 {
33 // 初始化
34 bool result = false;
35 TLinkItem* pItem = new TLinkItem;
36
37 // 加入隊列
38 if (pItem != NULL)
39 {
40 // 寫值
41 pItem->Data = AData;
42 pItem->Next = NULL;
43
44 // 加到末尾
45 FLinkTail->Next = pItem;
46 FLinkTail = pItem;
47
48 // 返回結果
49 result = true;
50 }
51
52 // 返回結果
53 return result;
54 }
55
56 // 取出
57 void* Pop()
58 {
59 // 初始化
60 void* result = NULL;
61
62 // 讀取項
63 if (FLinkHead->Next != NULL)
64 {
65 // 取值
66 TLinkItem* pItem = FLinkHead;
67 FLinkHead = FLinkHead->Next;
68 result = FLinkHead->Data;
69
70 // 釋放項
71 delete pItem;
72 }
73
74 // 返回結果
75 return result;
76 }
77