gpt4 book ai didi

c++ - 多线程应用程序中无锁队列的访问冲突

转载 作者:行者123 更新时间:2023-11-28 01:04:37 26 4
gpt4 key购买 nike

我根据下面 msdn 文章中概述的原则以及下面的 DXUT 无锁管道代码编写了一个简单的无锁队列:

因此,我有一个生产者/消费者模型设置,其中我的主线程提供渲染指令,而渲染线程使用可用消息并发出相应的 opengl 调用。如果我在每个循环/迭代中让我的主线程休眠足够长的时间,一切都会正常,但如果我没有让主线程休眠足够长的时间(或根本没有),我会收到访问冲突异常:

First-chance exception at 0x00b28d9c in Engine.exe: 0xC0000005: Access violation reading location 0x00004104.
Unhandled exception at 0x777715ee in Engine.exe: 0xC0000005: Access violation reading location 0x00004104.

我的调用堆栈是:

ntdll.dll!777715ee()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!777715ee()
ntdll.dll!7776015e()
Engine.exe!RingBuffer<2048>::BeginRead(void * & ppMem=, unsigned long & BytesAvailable=) Line 52 + 0x10 bytes C++
Engine.exe!Thread::ThreadMain(void * lpParam=0x00107d94) Line 41 + 0xf bytes C++

我不太清楚可能是什么问题。我的无锁队列的代码如下:

    template <uint32 BufferSize>
class RingBuffer
{
public:
RingBuffer()
: m_ReadOffset(0)
, m_WriteOffset(0)
{}
~RingBuffer()
{}

bool Empty() const
{
return (m_WriteOffset == m_ReadOffset);
}

void BeginRead(void*& ppMem, uint32& BytesAvailable)
{
const uint32 ReadOffset = m_ReadOffset;
const uint32 WriteOffset = m_WriteOffset;

AppReadWriteBarrier();

const uint32 Slack = (WriteOffset > ReadOffset) ?
(WriteOffset - ReadOffset) :
(ReadOffset > WriteOffset) ?
(c_BufferSize - ReadOffset) :
(0);

ppMem = (m_Buffer + ReadOffset);
BytesAvailable = Slack;
}

void EndRead(const uint32 BytesRead)
{
uint32 ReadOffset = m_ReadOffset;

AppReadWriteBarrier();

ReadOffset += BytesRead;
ReadOffset %= c_BufferSize;

m_ReadOffset = ReadOffset;
}

void BeginWrite(void*& ppMem, uint32& BytesAvailable)
{
const uint32 ReadOffset = m_ReadOffset;
const uint32 WriteOffset = m_WriteOffset;

AppReadWriteBarrier();

const uint32 Slack = (WriteOffset > ReadOffset || WriteOffset == ReadOffset) ?
(c_BufferSize - WriteOffset) :
(ReadOffset - WriteOffset);

ppMem = (m_Buffer + WriteOffset);
BytesAvailable = Slack;
}

void EndWrite(const uint32 BytesWritten)
{
uint32 WriteOffset = m_WriteOffset;

AppReadWriteBarrier();

WriteOffset += BytesWritten;
WriteOffset %= c_BufferSize;

m_WriteOffset = WriteOffset;
}

private:
const static uint32 c_BufferSize = NEXT_POWER_OF_2(BufferSize);
const static uint32 c_SizeMask = c_BufferSize - 1;

private:
byte8 m_Buffer[ c_BufferSize ];
volatile ALIGNMENT(4) uint32 m_ReadOffset;
volatile ALIGNMENT(4) uint32 m_WriteOffset;
};

我很难调试它,因为从监 window 口看读/写偏移量和缓冲区指针看起来很好。不幸的是,当应用程序中断时,我无法从 BeginRead 函数中查看自动/局部变量。如果有人有使用无锁编程的经验,将非常感谢对此问题的任何帮助或一般建议。

最佳答案

您可能会对这些文章感兴趣...

Lock-Free Code: A False Sense of Security
Writing Lock-Free Code: A Corrected Queue

在第一篇文章中,Herb Sutter 讨论了另一位作者对无锁队列的实现,并指出了一些可能出错的地方。在第二篇文章中,Herb 展示了对原始实现的一些更正。

作为学习练习,尝试构建您自己的无锁队列是一个不错的主意。但是对于生产工作,您可能更安全地从可靠来源找到一个预先存在的实现并使用它。例如,Concurrency Runtime提供 concurrent_queue

关于c++ - 多线程应用程序中无锁队列的访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6976405/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com