亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C/C++線程安全型隊列的實現?

C/C++線程安全型隊列的實現?

紫衣仙女 2018-11-14 19:15:57
編寫一個線程安全的隊列,所謂線程安全,就是該隊列能夠實現多個線程同時正確的增刪改隊列結點,也就是能夠實現對隊列這個臨界資源的保護。需要實現的函數包括:(1) InitQueue函數:初始化一個空的隊列,并初始化各個用于保護隊列的信號量。(2) EnQueue函數:在隊列尾部加入一個結點(3) DeQueue函數:刪除隊列頭部結點(4) Clear函數:刪除隊列中的所有結點(5) Find函數:查找隊列中是否有指定的元素,若有,返回能夠訪問該結點的指針;若無,返回NULL。(6) Print函數:打印當前隊列中的所有元素。完成該隊列后,自己編寫一個測試程序,生成多個線程同時讀寫該隊列,驗證你的隊列執行是否正確。我基本不會,所以請具體給出代碼(可以把代碼發我郵箱[email protected]),簡單的介紹我不會采納,我會先測試,無錯的話可以追加懸賞分。其中線性安全請用到互斥量Mutex,這是我先在在學的,所以很關鍵。
查看完整描述

1 回答

?
明月笑刀無情

TA貢獻1828條經驗 獲得超4個贊

首先,互斥量這種線程相關的內容是平臺相關的,我假設你用的是windows平臺開發。
其次,說明一下我的開發環境,vs2008,控制臺程序,空的工程。
最后給你貼代碼,分文件來看。

===頭文件QueueNode.h===
===你需要的節點數據可能不是整數,只要將typedef int QUEUEDATA這一句的int換成你想要的類型即可,但要注意,這個類型必須實現賦值操作符重載,相等比較操作符重載,以及復制構造函數===

#ifndef _QUEUE_NODE_H_
#define _QUEUE_NODE_H_

typedef int QUEUEDATA;

typedef struct node
{
QUEUEDATA data;
node* m_pNext;
}QUEUENODE;

#endif

===隊列頭文件Queue.h,有平臺相關內容,請注意===
#ifndef _QUEUE_H_
#define _QUEUE_H_

#include "QueueNode.h"
#include <Windows.h>

class ThreadSafeQueue
{
public:
ThreadSafeQueue();
virtual ~ThreadSafeQueue();

bool InitQueue();
void EnQueue(const QUEUEDATA& data);
void DeQueue();
void Clear();
const QUEUENODE* Find(const QUEUEDATA& data) const;
void Print();

protected:
HANDLE m_hMutex;
QUEUENODE* m_pQueueHead;
};

#endif

===隊列函數實現文件Queue.cpp===
#include "Queue.h"
#include <iostream>

ThreadSafeQueue::ThreadSafeQueue()
{
m_pQueueHead = new QUEUENODE;
m_pQueueHead->m_pNext = 0;
}

ThreadSafeQueue::~ThreadSafeQueue()
{
Clear();
delete m_pQueueHead;
CloseHandle(m_hMutex);
}

bool ThreadSafeQueue::InitQueue()
{
m_hMutex = CreateMutex(0, FALSE, 0);
return (m_hMutex!=0);
}

void ThreadSafeQueue::EnQueue(const QUEUEDATA& data)
{
WaitForSingleObject(m_hMutex, INFINITE);
QUEUENODE* pNode = new QUEUENODE;
pNode->data = data;
pNode->m_pNext = 0;
QUEUENODE* pTemp = m_pQueueHead;
while (pTemp->m_pNext != 0)
{
pTemp = pTemp->m_pNext;
}
pTemp->m_pNext = pNode;
ReleaseMutex(m_hMutex);
}

void ThreadSafeQueue::DeQueue()
{
WaitForSingleObject(m_hMutex, INFINITE);
QUEUENODE* pNode = m_pQueueHead->m_pNext;
if (pNode != 0)
{
m_pQueueHead->m_pNext = pNode->m_pNext;
delete pNode;
pNode = 0;
}
ReleaseMutex(m_hMutex);
}

const QUEUENODE* ThreadSafeQueue::Find(const QUEUEDATA& data) const
{
WaitForSingleObject(m_hMutex, INFINITE);
QUEUENODE* pNode = m_pQueueHead->m_pNext;
while (pNode != 0)
{
if (pNode->data == data)
{
break;
}
pNode = pNode->m_pNext;
}
return pNode;
ReleaseMutex(m_hMutex);
}

void ThreadSafeQueue::Clear()
{
WaitForSingleObject(m_hMutex, INFINITE);
QUEUENODE* pNode = m_pQueueHead->m_pNext;
QUEUENODE* pTemp = 0;
while (pNode != 0)
{
pTemp = pNode->m_pNext;
delete pNode;
pNode = pTemp;
}
m_pQueueHead->m_pNext = 0;
ReleaseMutex(m_hMutex);
}

void ThreadSafeQueue::Print()
{
WaitForSingleObject(m_hMutex, INFINITE);
QUEUENODE* pNode = m_pQueueHead->m_pNext;
while (pNode != 0)
{
std::cout << pNode->data << "\t";
pNode = pNode->m_pNext;
}
std::cout << std::endl;
ReleaseMutex(m_hMutex);
}

===測試代碼文件main.cpp,包含了測試用可執行程序,兩個操作queue的線程,需要說明的是,我本來打算用WaitMultipleObjects函數來等待兩個線程都結束,但是沒搞清楚是什么問題沒有卡住,不打算繼續糾纏它了,所以讓主線程Sleep了5秒鐘===
#include "Queue.h"
#include <iostream>

DWORD WINAPI HandleQueue(void* pParam);
DWORD WINAPI HandleQueue2(void* pParam);

int main()
{
ThreadSafeQueue queue;
queue.InitQueue();
HANDLE hThread[2] = {0};
DWORD threadID = 0;
hThread[0] = CreateThread(NULL, 0, HandleQueue, (void*)(&queue), NULL, &threadID);
hThread[0] = CreateThread(NULL, 0, HandleQueue2, (void*)(&queue), NULL, &threadID);

//WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
Sleep(5000);
queue.Print();
queue.Clear();
return 0;
}

DWORD WINAPI HandleQueue(void* pParam)
{
ThreadSafeQueue* pQueue = reinterpret_cast<ThreadSafeQueue*>(pParam);
for (int i = 0; i < 100; i++)
{
std::cout << "HandleQueue EnQueue" << std::endl;
pQueue->EnQueue(i);
}
for (int i = 0; i < 50; i++)
{
std::cout << "HandleQueue DeQueue" << std::endl;
pQueue->DeQueue();
}
return 0;
}

DWORD WINAPI HandleQueue2(void* pParam)
{
ThreadSafeQueue* pQueue = reinterpret_cast<ThreadSafeQueue*>(pParam);
for (int i = 0; i < 100; i++)
{
std::cout << "HandleQueue2 EnQueue" << std::endl;
pQueue->EnQueue(i+100);
}
for (int i = 0; i < 50; i++)
{
std::cout << "HandleQueue2 DeQueue" << std::endl;
pQueue->DeQueue();
}
return 0;
}

新建一個空的控制臺程序工程,向工程中加入這幾個文件,編譯之后可以直接運行。
第一個線程投入隊列100個元素,出隊50個元素,第二個線程同樣。最后主線程輸出隊列中最后的內容,然后清空。
隊列用鏈表實現,可以試想一下,如果線程同步沒有處理,指針操作時一定會引起崩潰



查看完整回答
反對 回復 2018-12-15
  • 1 回答
  • 0 關注
  • 2094 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號