=大小){ std::this_thread::sleep_for(std::chrono::纳秒(10)); 未读=写操作-读操作; } } int* CircularBuffer::getWritePos(){ WaitForReaderTocatachup(); int pos=writePos%大小; 返回和数据[pos]; } 无效的 CircularBuffer::finishedWriting(){ writePos++; } 无效的 循环缓冲::WaitForWriterTocatachup(){ int unread=writePos-readPos; 而(未读finishedWriting(); } } 无效消耗(循环缓冲*cb){ 对于(int i=0;igetReadPos(); int j=*p; std::cout k; },c++,multithreading,C++,Multithreading" /> =大小){ std::this_thread::sleep_for(std::chrono::纳秒(10)); 未读=写操作-读操作; } } int* CircularBuffer::getWritePos(){ WaitForReaderTocatachup(); int pos=writePos%大小; 返回和数据[pos]; } 无效的 CircularBuffer::finishedWriting(){ writePos++; } 无效的 循环缓冲::WaitForWriterTocatachup(){ int unread=writePos-readPos; 而(未读finishedWriting(); } } 无效消耗(循环缓冲*cb){ 对于(int i=0;igetReadPos(); int j=*p; std::cout k; },c++,multithreading,C++,Multithreading" />

我的生产者-消费者代码中是否存在死锁或竞争条件? 我试图在C++中实现生产者-消费者模式。 当我读到这种模式时,他们似乎总是提到必须避免的潜在僵局。 但是,我在下面实现了这一点,没有使用下面的任何互斥。 我的代码有什么问题 #include <vector> #include <iostream> #include <chrono> #include <thread> #include <atomic> class CircularBuffer { public: CircularBuffer(); int* getWritePos(); void finishedWriting(); int* getReadPos(); void finishedReading(); private: void waitForReaderToCatchUp(); void waitForWriterToCatchUp(); const int size = 5; std::vector<int> data; // Changed from int since these variables are shared between the two threads and assignment is not necessarily atomic: std::atomic<int> writePos = 0; std::atomic<int> readPos = 0; }; CircularBuffer::CircularBuffer() { data.resize(size); } void CircularBuffer::waitForReaderToCatchUp() { int unread = writePos - readPos; while (unread >= size) { std::this_thread::sleep_for(std::chrono::nanoseconds(10)); unread = writePos - readPos; } } int* CircularBuffer::getWritePos() { waitForReaderToCatchUp(); int pos = writePos % size; return &data[pos]; } void CircularBuffer::finishedWriting() { writePos++; } void CircularBuffer::waitForWriterToCatchUp() { int unread = writePos - readPos; while (unread < 1) { std::this_thread::sleep_for(std::chrono::nanoseconds(10)); unread = writePos - readPos; } } int* CircularBuffer::getReadPos() { waitForWriterToCatchUp(); int pos = readPos % size; return &data[pos]; } void CircularBuffer::finishedReading() { readPos++; } const int produceMinTime = 100; void produce(CircularBuffer *cb) { for (int i = 0; i < 15; i++) { int r = rand() % 1000; std::this_thread::sleep_for(std::chrono::milliseconds(produceMinTime + r)); int *p = cb->getWritePos(); memcpy(p, &i, 4); cb->finishedWriting(); } } void consume(CircularBuffer *cb) { for (int i = 0; i < 15; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); int *p = cb->getReadPos(); int j = *p; std::cout << "Value: " << j << std::endl; cb->finishedReading(); } } int main() { CircularBuffer cb; std::thread t1(produce, &cb); std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::thread t2(consume, &cb); t1.join(); t2.join(); int k; std::cin >> k; } #包括 #包括 #包括 #包括 #包括 类循环缓冲 { 公众: 循环缓冲(); int*getWritePos(); 无效完成的书写(); int*getReadPos(); 无效完成恐惧(); 私人: void waitForReaderTocatachup(); void waitForWriterToCatchUp(); 常数int size=5; std::矢量数据; //更改为int,因为这些变量在两个线程之间共享,并且赋值不一定是原子的: std::原子写操作=0; 标准::原子读取位置=0; }; CircularBuffer::CircularBuffer(){ 数据。调整大小(大小); } 无效的 循环缓冲::WaitForReaderTocatachup(){ int unread=writePos-readPos; while(未读>=大小){ std::this_thread::sleep_for(std::chrono::纳秒(10)); 未读=写操作-读操作; } } int* CircularBuffer::getWritePos(){ WaitForReaderTocatachup(); int pos=writePos%大小; 返回和数据[pos]; } 无效的 CircularBuffer::finishedWriting(){ writePos++; } 无效的 循环缓冲::WaitForWriterTocatachup(){ int unread=writePos-readPos; 而(未读finishedWriting(); } } 无效消耗(循环缓冲*cb){ 对于(int i=0;igetReadPos(); int j=*p; std::cout k; }

我的生产者-消费者代码中是否存在死锁或竞争条件? 我试图在C++中实现生产者-消费者模式。 当我读到这种模式时,他们似乎总是提到必须避免的潜在僵局。 但是,我在下面实现了这一点,没有使用下面的任何互斥。 我的代码有什么问题 #include <vector> #include <iostream> #include <chrono> #include <thread> #include <atomic> class CircularBuffer { public: CircularBuffer(); int* getWritePos(); void finishedWriting(); int* getReadPos(); void finishedReading(); private: void waitForReaderToCatchUp(); void waitForWriterToCatchUp(); const int size = 5; std::vector<int> data; // Changed from int since these variables are shared between the two threads and assignment is not necessarily atomic: std::atomic<int> writePos = 0; std::atomic<int> readPos = 0; }; CircularBuffer::CircularBuffer() { data.resize(size); } void CircularBuffer::waitForReaderToCatchUp() { int unread = writePos - readPos; while (unread >= size) { std::this_thread::sleep_for(std::chrono::nanoseconds(10)); unread = writePos - readPos; } } int* CircularBuffer::getWritePos() { waitForReaderToCatchUp(); int pos = writePos % size; return &data[pos]; } void CircularBuffer::finishedWriting() { writePos++; } void CircularBuffer::waitForWriterToCatchUp() { int unread = writePos - readPos; while (unread < 1) { std::this_thread::sleep_for(std::chrono::nanoseconds(10)); unread = writePos - readPos; } } int* CircularBuffer::getReadPos() { waitForWriterToCatchUp(); int pos = readPos % size; return &data[pos]; } void CircularBuffer::finishedReading() { readPos++; } const int produceMinTime = 100; void produce(CircularBuffer *cb) { for (int i = 0; i < 15; i++) { int r = rand() % 1000; std::this_thread::sleep_for(std::chrono::milliseconds(produceMinTime + r)); int *p = cb->getWritePos(); memcpy(p, &i, 4); cb->finishedWriting(); } } void consume(CircularBuffer *cb) { for (int i = 0; i < 15; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); int *p = cb->getReadPos(); int j = *p; std::cout << "Value: " << j << std::endl; cb->finishedReading(); } } int main() { CircularBuffer cb; std::thread t1(produce, &cb); std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::thread t2(consume, &cb); t1.join(); t2.join(); int k; std::cin >> k; } #包括 #包括 #包括 #包括 #包括 类循环缓冲 { 公众: 循环缓冲(); int*getWritePos(); 无效完成的书写(); int*getReadPos(); 无效完成恐惧(); 私人: void waitForReaderTocatachup(); void waitForWriterToCatchUp(); 常数int size=5; std::矢量数据; //更改为int,因为这些变量在两个线程之间共享,并且赋值不一定是原子的: std::原子写操作=0; 标准::原子读取位置=0; }; CircularBuffer::CircularBuffer(){ 数据。调整大小(大小); } 无效的 循环缓冲::WaitForReaderTocatachup(){ int unread=writePos-readPos; while(未读>=大小){ std::this_thread::sleep_for(std::chrono::纳秒(10)); 未读=写操作-读操作; } } int* CircularBuffer::getWritePos(){ WaitForReaderTocatachup(); int pos=writePos%大小; 返回和数据[pos]; } 无效的 CircularBuffer::finishedWriting(){ writePos++; } 无效的 循环缓冲::WaitForWriterTocatachup(){ int unread=writePos-readPos; 而(未读finishedWriting(); } } 无效消耗(循环缓冲*cb){ 对于(int i=0;igetReadPos(); int j=*p; std::cout k; },c++,multithreading,C++,Multithreading,std::vector不是线程安全的数据结构。因此,如果您同时从两个线程访问它,这将被视为未定义的行为。您可能会崩溃,出现其他问题,或者它看起来可能工作(但仍然是错误的) 向量中的int和表示位置的int也不是线程安全的——读/写不一定是原子的(有无锁的方法) 因此,您完全可以实现这种无锁的功能,但不是这样。此处提供一些信息: 通常,您希望查看std::atomic中的原语: 另请参见:我不明白您的问题是什么?如果您没有类似互斥锁的东西,那么就不会有死锁。不确定此代码中是否存在死锁-您必须询问提

std::vector
不是线程安全的数据结构。因此,如果您同时从两个线程访问它,这将被视为未定义的行为。您可能会崩溃,出现其他问题,或者它看起来可能工作(但仍然是错误的)

向量中的int和表示位置的int也不是线程安全的——读/写不一定是原子的(有无锁的方法)

因此,您完全可以实现这种无锁的功能,但不是这样。此处提供一些信息:

通常,您希望查看std::atomic中的原语:


另请参见:

我不明白您的问题是什么?如果您没有类似互斥锁的东西,那么就不会有死锁。不确定此代码中是否存在死锁-您必须询问提出此问题的人-但无论何时您看到
此线程::sleep\u for()
应该提出问题您不会出现死锁,但情况更糟:由于数据竞争,行为未定义。您需要同步原语来防止它们。代码不起作用,问题是它没有经过足够好的测试。数据竞争错误每月只发生一次,大约一个月。另一个值得注意的缺陷是在现代机器上,毫秒是永恒的。不要自己写,谷歌“c++线程安全循环缓冲区”找到代码。@HansPassant:谢谢。我把它改为10纳秒。谢谢你的帮助!如果我把writePos和readPos改为atomic,那就可以解决你第二段中关于std::vector不是线程安全的问题了。据我所知,从不同线程读取是可以的?在我的情况下,我读写都可以。但是我从来没有写过e并同时读取同一个元素。生产者始终比使用者至少提前1个元素。而且向量的大小永远不会调整。这是否正常?:“同一容器上的不同线程可以并发调用所有常量成员函数。”,“运算符[],出于线程安全的目的,其行为与常量相同”,“同一容器中的不同元素可以由不同的线程同时修改”。太好了。那么您仍然需要处理pos变量。