C++ 从3个线程访问std::deque
我有一个std::deque类型的缓冲区。 有一个线程要写入,另一个线程要从中读取,最后一个线程要处理缓冲区中要转发的项目的某些条件 我只想从3个线程安全地访问这个缓冲区。是的,我是个初学者:-) 我创建了一个互斥体,每次访问缓冲区时,我都会通过C++ 从3个线程访问std::deque,c++,multithreading,mutex,C++,Multithreading,Mutex,我有一个std::deque类型的缓冲区。 有一个线程要写入,另一个线程要从中读取,最后一个线程要处理缓冲区中要转发的项目的某些条件 我只想从3个线程安全地访问这个缓冲区。是的,我是个初学者:-) 我创建了一个互斥体,每次访问缓冲区时,我都会通过 myMutex. lock() ; // access here myMutex. unlock() ; 此外,我还使用std::thread myThread(this,&fn)来创建线程。我经常调用这个线程::sleep(),以减少cpu负载 我
myMutex. lock() ;
// access here
myMutex. unlock() ;
此外,我还使用std::thread myThread(this,&fn)来创建线程。我经常调用这个线程::sleep(),以减少cpu负载
我的问题是我得到了一个解释说abort()已经被调用了!当我调试它时,调用myThread.join()失败
有什么错
编辑:添加代码
这是我的主要发送功能
void UDPStreamSender::SendStream(const char* sendMsg, size_t size)
{
cout << "---- Send Stream starts... ----" << endl;
char* longMsg = new char[size];
memcpy(longMsg, sendMsg, size);
std::thread segThread(&UDPStreamSender::DoSegmentation, this, longMsg, size);
_isRunning = true;
std::thread sendThrad(&UDPStreamSender::SendBuffer, this);
std::thread ackThrad(&UDPStreamSender::AckRecive, this);
std::thread timeOutThread(&UDPStreamSender::ManageTimeout, this);
sendThrad.join();
ackThrad.join();
timeOutThread.join();
cout << "---- Send Stream done! ----" << endl;
}
void UDPStreamSender::SendStream(const char*sendMsg,size\u t size)
{
我试了又试!
错误来自我锁定互斥锁()和解锁互斥锁()的方式
即使用bufLock.lock()
,使用std::unique_lock mtx_lock(bufLock);
锁定数据块缓冲区
此外,还需要两个变量_条件来处理isEmpty和isFull的情况,以停止转发,并添加到缓冲区
如果有人认为最终的代码有用,那么它就是最终的代码
注意:此代码占用大量内存和CPU,未经修订请勿使用。欢迎帮助我:)
void UDPStreamSender::SendStream(const char*sendMsg,size\u t size)
{
InitializeNewSendSession();
cout data=新字符[msgSegLen];
int sendmsgeglen=msgSegLen;
if(i==segmentsNumber-1)
sendMsgSegLen=msgLength-i*msgSegLen;
memcpy(cSeg->data,longMsg+i*msgSegLen,sendmsgeglen);
//添加到发送缓冲区
标准:唯一锁mtx锁(bufLock);
而(sendBuffer->isFull())
{
停止完全等待(mtx_锁);
}
cSeg->isSent=false;
sendBuffer->Add(cSeg);
mtx_lock.unlock();
stopIfEmpty.notify_all();
}
}
int UDPStreamSender::SendSegment(常量段*seg)
{
char*sMsg=新字符[segLength];
sMsg[0]=NULL;
memcpy(sMsg,(char*)&seg->seqNum,SEQ_NUM_LEN);
memcpy(sMsg+序号,seg->data,msgSegLen);
int st=streamSender->Send(sMsg,segLength);
删除sMsg;
返回st;
}
无效UDPStreamSender::SendBuffer()
{
bufLock.lock();
bool hasElms=sendBuffer->hasElems();
bufLock.unlock();
当(|正在运行| | hasElms)
{
标准:唯一锁mtx锁(bufLock);
size\u t firstUnsent=sendBuffer->firstUnsent();
size\u t buffCount=sendBuffer->count();
而(!sendBuffer->hasElems())
{
stopIfEmpty.wait_for(mtx_锁,std::chrono::毫秒(100));
如果(所有收到)
返回;
}
对于(大小i=firstUnsent;iat(i);
int st=发送段(&sSeg);
如果(st>=segLength)
{
sSeg.ISENT=真;
DWORD j=GetTickCount();
sSeg.timeOutTick=j+timeOutTicks;
sendBuffer->Replace(i和sSeg);
sendBuffer->sendSeg();
cout hasElems())
{
stopIfEmpty.wait_for(mtx_锁,std::chrono::毫秒(100));
如果(所有收到)
返回;
}
DWORD segTick=sendBuffer->first().timeOutTick;
DWORD cTick=GetTickCount();
if(sendBuffer->hasElems()&&cTick>segTick)
{//超时,重新发送所有缓冲区
sendBuffer->resendAll();
难道代码在哪里?你的lock/unlock片段没有说明问题的真正原因。你是否尝试过使用-pthread
编译?@Smac89我添加了代码。@KerrekSB我真的不知道什么是“-pthread”!-pthread
是一个编译器选项。就像在不支持该选项的编译器中为编译c++11代码添加-std=gnu++11
一样,-pthread
用于编译posix线程代码。
void UDPStreamSender::DoSegmentation(const char* longMsg, unsigned int size)
{
Segment* cSeg = new Segment();
cSeg->seqNum = lastSeqNum;
msgLength = size;
msgSegLen = segLength - SEQ_NUM_LEN;
segmentsNumber = (unsigned int)ceil((float)msgLength / (msgSegLen));
for (size_t i = 0; i < segmentsNumber; i++)
{
cSeg->seqNum++;
lastSeqNum = cSeg->seqNum;
cSeg->data = new char[msgSegLen];
int sendMsgSegLen = msgSegLen;
if (i == segmentsNumber - 1)
sendMsgSegLen = msgLength - i*msgSegLen;
memcpy(cSeg->data, longMsg + i*msgSegLen, sendMsgSegLen);
// Add to send buffer
while (sendBuffer->isFull())
{
this_thread::sleep_for(std::chrono::milliseconds(50));
}
cSeg->isSent = false;
bufLock.lock();
std::unique_lock<std::mutex> lock(bufLock);
sendBuffer->Add(cSeg);
bufLock.unlock();
}
cv.notify_all();
}
void UDPStreamSender::SendBuffer()
{
bufLock.lock();
bool hasElms = sendBuffer->hasElems();
bufLock.unlock();
while (_isRunning || hasElms)
{
bufLock.lock();
size_t firstUnsent = sendBuffer->firstUnsent();
size_t buffCount = sendBuffer->count();
bufLock.unlock();
if (firstUnsent == buffCount)
{
this_thread::sleep_for(std::chrono::milliseconds(50));
continue;
}
for (size_t i = firstUnsent; i < buffCount; i++)
{
bufLock.lock();
Segment sSeg = sendBuffer->at(i);
int st = SendSegment(&sSeg);
if (st >= segLength)
{
sSeg.isSent = true;
DWORD j = GetTickCount();
sSeg.timeOutTick = j + timeOutTicks;
sendBuffer->Replace(i, &sSeg);
sendBuffer->sendSeg();
cout << "SEG sent: SeqNum=" << sSeg.seqNum << endl;
}
bufLock.unlock();
}
bufLock.lock();
hasElms = sendBuffer->hasElems();
bufLock.unlock();
}
}
void UDPStreamSender::AckRecive()
{
char* ackMessage;
while (!_allRecived)
{
ackMessage = ackReciver->Recive();
string ackMsg(ackMessage);
if (ackMsg.substr(0, 3).compare("ACK") != 0)
continue;
unsigned short ackSeqNum = 0;
memcpy(&ackSeqNum, ackMessage + 3, 2);
cout << "ACK recieved: seqNum=" << ackSeqNum << endl;
bufLock.lock();
sendBuffer->Ack(ackSeqNum);
_allRecived = !sendBuffer->hasElems();
bufLock.unlock();
}
}
void UDPStreamSender::ManageTimeout()
{
bufLock.lock();
bool hasElms = sendBuffer->hasElems();
bufLock.unlock();
while (hasElms)
{
bufLock.lock();
DWORD segTick = sendBuffer->first().timeOutTick;
DWORD cTick = GetTickCount();
if (sendBuffer->hasElems() && cTick > segTick)
{ // timeout, resend all buffer
sendBuffer->resendAll();
cout << "Timeout: seqNum=" << sendBuffer->first().seqNum << endl;
}
bufLock.unlock();
this_thread::sleep_for(std::chrono::milliseconds(50));
bufLock.lock();
hasElms = sendBuffer->hasElems();
bufLock.unlock();
}
}
void UDPStreamSender::SendStream(const char* sendMsg, size_t size)
{
InitializeNewSendSession();
cout << "---- Send Stream starts... ----" << endl;
char* longMsg = new char[size];
memcpy(longMsg, sendMsg, size);
std::thread segThread(&UDPStreamSender::DoSegmentation, this, longMsg, size);
_isRunning = true;
std::thread sendThrad(&UDPStreamSender::SendBuffer, this);
std::thread ackThrad(&UDPStreamSender::AckRecive, this);
std::thread timeOutThread(&UDPStreamSender::ManageTimeout, this);
segThread.join();
sendThrad.join();
_isRunning = false;
ackThrad.join();
timeOutThread.join();
cout << "---- Send Stream done! ----" << endl;
}
void UDPStreamSender::DoSegmentation(const char* longMsg, unsigned int size)
{
Segment* cSeg = new Segment();
cSeg->seqNum = lastSeqNum;
msgLength = size;
msgSegLen = segLength - SEQ_NUM_LEN;
segmentsNumber = (unsigned int)ceil((float)msgLength / (msgSegLen));
for (size_t i = 0; i < segmentsNumber; i++)
{
cSeg->seqNum++;
lastSeqNum = cSeg->seqNum;
cSeg->data = new char[msgSegLen];
int sendMsgSegLen = msgSegLen;
if (i == segmentsNumber - 1)
sendMsgSegLen = msgLength - i*msgSegLen;
memcpy(cSeg->data, longMsg + i*msgSegLen, sendMsgSegLen);
// Add to send buffer
std::unique_lock<std::mutex> mtx_lock(bufLock);
while (sendBuffer->isFull())
{
stopifFull.wait(mtx_lock);
}
cSeg->isSent = false;
sendBuffer->Add(cSeg);
mtx_lock.unlock();
stopIfEmpty.notify_all();
}
}
int UDPStreamSender::SendSegment(const Segment* seg)
{
char* sMsg = new char[segLength];
sMsg[0] = NULL;
memcpy(sMsg, (char*)&seg->seqNum, SEQ_NUM_LEN);
memcpy(sMsg + SEQ_NUM_LEN, seg->data, msgSegLen);
int st = streamSender->Send(sMsg, segLength);
delete sMsg;
return st;
}
void UDPStreamSender::SendBuffer()
{
bufLock.lock();
bool hasElms = sendBuffer->hasElems();
bufLock.unlock();
while (_isRunning || hasElms)
{
std::unique_lock<std::mutex> mtx_lock(bufLock);
size_t firstUnsent = sendBuffer->firstUnsent();
size_t buffCount = sendBuffer->count();
while (!sendBuffer->hasElems())
{
stopIfEmpty.wait_for(mtx_lock, std::chrono::milliseconds(100));
if (_allRecived)
return;
}
for (size_t i = firstUnsent; i < buffCount; i++)
{
Segment sSeg = sendBuffer->at(i);
int st = SendSegment(&sSeg);
if (st >= segLength)
{
sSeg.isSent = true;
DWORD j = GetTickCount();
sSeg.timeOutTick = j + timeOutTicks;
sendBuffer->Replace(i, &sSeg);
sendBuffer->sendSeg();
cout << "SEG sent: SeqNum=" << sSeg.seqNum << endl;
}
}
hasElms = sendBuffer->hasElems();
mtx_lock.unlock();
}
}
void UDPStreamSender::AckRecive()
{
char* ackMessage;
while (!_allRecived)
{
ackMessage = ackReciver->Recive();
string ackMsg(ackMessage);
if (ackMsg.substr(0, 3).compare("ACK") != 0)
continue;
unsigned short ackSeqNum = 0;
memcpy(&ackSeqNum, ackMessage + 3, 2);
cout << "ACK recieved: seqNum=" << ackSeqNum << endl;
std::unique_lock<mutex> mtx_lock(bufLock);
sendBuffer->Ack(ackSeqNum);
_allRecived = !sendBuffer->hasElems() || !_isRunning;
mtx_lock.unlock();
stopifFull.notify_one();
}
}
void UDPStreamSender::ManageTimeout()
{
bufLock.lock();
bool hasElms = sendBuffer->hasElems();
bufLock.unlock();
while (!_allRecived)
{
std::unique_lock<mutex> mtx_lock(bufLock);
while (!sendBuffer->hasElems())
{
stopIfEmpty.wait_for(mtx_lock, std::chrono::milliseconds(100));
if (_allRecived)
return;
}
DWORD segTick = sendBuffer->first().timeOutTick;
DWORD cTick = GetTickCount();
if (sendBuffer->hasElems() && cTick > segTick)
{ // timeout, resend all buffer
sendBuffer->resendAll();
cout << "Timeout: seqNum=" << sendBuffer->first().seqNum << endl;
}
hasElms = sendBuffer->hasElems();
mtx_lock.unlock();
}
}