Multithreading std::条件变量::等待访问冲突

Multithreading std::条件变量::等待访问冲突,multithreading,c++11,concurrency,Multithreading,C++11,Concurrency,我目前正在编写一个并发队列,同时学习如何使用C++11的多线程功能。 当使用者调用dequeue()函数且队列没有条目时,该函数应等待另一个线程调用enqueue()。我使用了一个条件变量。 我的测试只使用了几个条目和线程,但当我使用更多元素(多达100000个元素,20个生产者,只有一个消费者)时,我在条件变量::wait函数中遇到了访问冲突: 在Tests.exe中取消对Ausnahme bei 0x5A2C7EEC(msvcr110d.dll)的绑定: 0xC0000005:Zugriff

我目前正在编写一个并发队列,同时学习如何使用C++11的多线程功能。 当使用者调用
dequeue()
函数且队列没有条目时,该函数应等待另一个线程调用
enqueue()
。我使用了一个
条件变量
。
我的测试只使用了几个条目和线程,但当我使用更多元素(多达100000个元素,20个生产者,只有一个消费者)时,我在
条件变量::wait
函数中遇到了访问冲突:

在Tests.exe中取消对Ausnahme bei 0x5A2C7EEC(msvcr110d.dll)的绑定: 0xC0000005:Zugriffsverletzung beim Lesen位置0xFEEEFEF6

这件事我已经坚持了好几个小时了。我希望你能帮助我。多谢各位

守则:

// --------------------------------------------------------------------------------------
// Concurrent Queue
// --------------------------------------------------------------------------------------

#pragma once
#include <atomic> // Atomic operations for lock-free operations
#include <mutex>
#include <condition_variable>
using namespace std;


// --------------------------------------------------------------------------------------
// Declarations
// --------------------------------------------------------------------------------------

template<typename T>
class ConcurrentQueue;

template<typename T>
class ConcurrentQueueEntry;


// --------------------------------------------------------------------------------------
// Queue
// --------------------------------------------------------------------------------------

template<typename T>
class ConcurrentQueue {
public:
    ConcurrentQueue();
    ~ConcurrentQueue();

    void enqueue(const T value);
    T try_dequeue();
    T dequeue();

    unsigned long count() const;

private:
    atomic<ConcurrentQueueEntry<T>*> front;
    atomic<ConcurrentQueueEntry<T>*> rear;

    atomic_ulong i_count;

    mutex dequeueWaitMutex;
    condition_variable dequeueWaitCV;
};


// --------------------------------------------------------------------------------------
// Entry
// --------------------------------------------------------------------------------------

template<typename T>
class ConcurrentQueueEntry {
public:
    ConcurrentQueueEntry(T _value);

    T value;
    atomic<ConcurrentQueueEntry<T>*> next;
};


// --------------------------------------------------------------------------------------
// Exception: Queue is empty
// --------------------------------------------------------------------------------------

class EmptyQueueException {};


// --------------------------------------------------------------------------------------
// Constructors and Destructor
// --------------------------------------------------------------------------------------

// Create Queue
template<typename T>
ConcurrentQueue<T>::ConcurrentQueue()
    : front(), rear(), i_count(), dequeueWaitMutex(), dequeueWaitCV()
{
    i_count.store(0);
}

// Delete Queue
template<typename T>
ConcurrentQueue<T>::~ConcurrentQueue()
{
    ConcurrentQueueEntry<T>* previous = this->front.load();
    while(previous != NULL) {
        ConcurrentQueueEntry<T>* next = previous->next.load();
        delete previous;
        previous = next;
    }
}

// Create Entry
template<typename T>
ConcurrentQueueEntry<T>::ConcurrentQueueEntry
    (T _value)
    : value(_value), next(NULL)
{ }


// --------------------------------------------------------------------------------------
// Public Methods
// --------------------------------------------------------------------------------------

// Enqueue
template<typename T>
void ConcurrentQueue<T>::enqueue
    (const T value)
{
    // create, append
    ConcurrentQueueEntry<T>* entry = new ConcurrentQueueEntry<T>(value);
    ConcurrentQueueEntry<T>* former_rear = this->rear.exchange(entry);

    // connect
    if(former_rear == NULL) {
        this->front.store(entry);
    }
    else {
        former_rear->next.store(entry);
    }

    // Add
    ++i_count;
    dequeueWaitCV.notify_one();
}

// Dequeue (aborts if queue is empty)
template<typename T>
T ConcurrentQueue<T>::try_dequeue()
{
    ConcurrentQueueEntry<T>* front = this->front.load();
    while(front != NULL && 
        !this->front.compare_exchange_weak(front, front->next.load())); 

    if(front == NULL)
        throw EmptyQueueException();

    --i_count;
    T value = front->value;
    delete front;
    return value;
}

// Dequeue (waits if queue is empty)
template<typename T>
T ConcurrentQueue<T>::dequeue() {
    while(true) {
        try {
            return this->try_dequeue();
        }
        catch(EmptyQueueException) {
            unique_lock<mutex> lock(dequeueWaitMutex);
            dequeueWaitCV.wait(lock, [&] { return this->count() == 0; });
        }
    }
}

// Count entries
template<typename T>
unsigned long ConcurrentQueue<T>::count() const {
    return this->i_count.load();
}
//--------------------------------------------------------------------------------------
//并发队列
// --------------------------------------------------------------------------------------
#布拉格语一次
#包含//用于无锁操作的原子操作
#包括
#包括
使用名称空间std;
// --------------------------------------------------------------------------------------
//声明
// --------------------------------------------------------------------------------------
样板
类并发队列;
样板
类ConcurrentQueueEntry;
// --------------------------------------------------------------------------------------
//排队
// --------------------------------------------------------------------------------------
样板
类并发队列{
公众:
ConcurrentQueue();
~ConcurrentQueue();
无效排队(常数T值);
不要尝试退出队列();
T退出队列();
无符号长计数()常量;
私人:
原子锋;
原子后部;
原子计数;
互斥体出列等待互斥体;
条件变量dequeueWaitCV;
};
// --------------------------------------------------------------------------------------
//入口
// --------------------------------------------------------------------------------------
样板
类ConcurrentQueueEntry{
公众:
ConcurrentQueueEntry(T_值);
T值;
原子下一步;
};
// --------------------------------------------------------------------------------------
//异常:队列为空
// --------------------------------------------------------------------------------------
类EmptyQueueException{};
// --------------------------------------------------------------------------------------
//构造函数和析构函数
// --------------------------------------------------------------------------------------
//创建队列
样板
ConcurrentQueue::ConcurrentQueue()
:front(),rear(),i_count(),dequeueWaitMutex(),dequeueWaitCV()
{
i_计数存储(0);
}
//删除队列
样板
ConcurrentQueue::~ConcurrentQueue()
{
ConcurrentQueueEntry*previous=this->front.load();
while(上一个!=NULL){
ConcurrentQueueEntry*next=previous->next.load();
删除以前的;
上一个=下一个;
}
}
//创建条目
样板
ConcurrentQueueEntry::ConcurrentQueueEntry
(T_值)
:值(_值),下一个(空)
{ }
// --------------------------------------------------------------------------------------
//公共方法
// --------------------------------------------------------------------------------------
//排队
样板
void ConcurrentQueue::enqueue
(常数T值)
{
//创建、附加
ConcurrentQueueEntry*entry=新的ConcurrentQueueEntry(值);
ConcurrentQueueEntry*前/后=此->后.exchange(条目);
//连接
如果(前/后==NULL){
此->前端存储(条目);
}
否则{
前/后->下一个存储(条目);
}
//加
++我数;
dequeueWaitCV.notify_one();
}
//退出队列(如果队列为空,则中止)
样板
T ConcurrentQueue::try_dequeue()
{
ConcurrentQueueEntry*front=this->front.load();
while(front!=NULL&&
!this->front.compare_exchange_弱(front,front->next.load());
if(front==NULL)
抛出EmptyQueueException();
--我数;
T值=前->值;
删除前端;
返回值;
}
//出列(队列为空时等待)
样板
T ConcurrentQueue::dequeue(){
while(true){
试一试{
返回此->尝试退出队列();
}
捕获(EmptyQueueException){
唯一锁(出列等待互斥锁);
wait(锁,[&]{返回此->计数()==0;});
}
}
}
//计数条目
样板
无符号长ConcurrentQueue::count()常量{
返回此->i_count.load();
}
调用堆栈:

msvcr110d.dll!Concurrency::details::LockQueueNode::IsTicketValid() Zeile 924    C++
msvcr110d.dll!Concurrency::details::LockQueueNode::UpdateQueuePosition(Concurrency::details::LockQueueNode * pPreviousNode) Zeile 811   C++
msvcr110d.dll!Concurrency::critical_section::_Acquire_lock(void * _PLockingNode, bool _FHasExternalNode) Zeile 1193 C++
msvcr110d.dll!Concurrency::critical_section::lock() Zeile 1028  C++
msvcr110d.dll!Concurrency::details::_Condition_variable::wait(Concurrency::critical_section & _Lck) Zeile 576   C++
msvcp110d.dll!do_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx, const xtime * target) Zeile 47 C++
msvcp110d.dll!_Cnd_wait(_Cnd_internal_imp_t * * cond, _Mtx_internal_imp_t * * mtx) Zeile 73 C++
Tests.exe!std::_Cnd_waitX(_Cnd_internal_imp_t * * _Cnd, _Mtx_internal_imp_t * * _Mtx) Zeile 93  C++
Tests.exe!std::condition_variable::wait(std::unique_lock<std::mutex> & _Lck) Zeile 60   C++
Tests.exe!std::condition_variable::wait<<lambda_61c2d1dffb87d02ed418fe62879bb063> >(std::unique_lock<std::mutex> & _Lck, ConcurrentQueue<long>::dequeue::__l7::<lambda_61c2d1dffb87d02ed418fe62879bb063> _Pred) Zeile 67    C++
Tests.exe!ConcurrentQueue<long>::dequeue() Zeile 156    C++
Tests.exe!<lambda_c8c79a4136723f6fef9d0a0557ed768b>::operator()() Zeile 38  C++
Tests.exe!std::_Bind<0,void,<lambda_c8c79a4136723f6fef9d0a0557ed768b>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Zeile 1152   C++
Tests.exe!std::_LaunchPad<std::_Bind<0,void,<lambda_c8c79a4136723f6fef9d0a0557ed768b>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> >::_Run(std::_LaunchPad<std::_Bind<0,void,<lambda_c8c79a4136723f6fef9d0a0557ed768b>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> > * _Ln) Zeile 196  C++
Tests.exe!std::_LaunchPad<std::_Bind<0,void,<lambda_c8c79a4136723f6fef9d0a0557ed768b>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> >::_Go() Zeile 187 C++
msvcp110d.dll!_Call_func(void * _Data) Zeile 52 C++
msvcr110d.dll!_callthreadstartex() Zeile 354    C
msvcr110d.dll!_threadstartex(void * ptd) Zeile 337  C
kernel32.dll!747f850d() Unbekannt
[Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für kernel32.dll] 
ntdll.dll!7719bf39()    Unbekannt
ntdll.dll!7719bf0c()    Unbekannt
msvcr110d.dll!并发::细节:锁QueLeNoDo::ISTICKEVALID()ZeILE 924 C++
msvcr110d.dll!并发::细节::CuffQueLeNoDe::UpDeaQueUePosie:(并发::细节:锁QueLeNoDe*PPRVIVE节点)蔡尔811 C++
msvcr110d.dll!并发::MajalLyC++部分::
msvcr110d.dll!并发::C++:(1028)CIELE
msvcr110d.dll!并发::细节::Apple:AtgulixValu::等待(并发::MaxalLySeal&Lyk)ZeILE 576 C++
msvcp110d.dll!doiWAIT(αnCNDIILIALALIMPIMPTH**COND,γMTX InILLATILIMPUT***MTX,const XTIME*Target)ZeILE 47 C++
msvcp110d.dll_CNDY-WAIT(αCNDIIN ILATALILIMPUTT **COND,γMTX InILALALIMPUT***MTX)ZeILE 73 C++
Tests.exe!STD::YNCdWaWiTx(αCNDIILIALALL IMPUTT ***CND,γMTX InILL LIMPHT***MTX)ZeILE 93 C++
Tests.exe!STD::条件变量::等待(STD::UngQuiHyLand and LLK)蔡尔60 C++
Tests.exe!STD::条件变量::等待(STD:UNIQUIGHOLD和OLLCK,并发队列::DEQue:::α-L7::O-PRED)蔡尔67 C++
Tests.exe!并发队列::DeQueEE()ZeILE 156 C++
Tests.exe!::()ZeILE 38 C++
Tests.exe!STD::{Bi::操作符()(ZeILE 1152 C++)
Tests.exe!STD::X发射板::运行(STD::X发射垫*α-LN)蔡尔196 C++
Tests.exe!std::\U Lau