有人能帮我找出低锁列表中的错误吗? 我在Windows 32位上用C++编写了一个低锁列表。与使用关键部分相比,我有了很大的改进,但我希望有人检查我所做的是否正确,以及我所做的是否有任何错误: #ifndef __LOW_LOCK_STACK_H_ #define __LOW_LOCK_STACK_H_ template< class T > class LowLockStack { protected: struct Entry { Entry* pNext; T* pData; }; union Header { __int64 m_XChg; struct { Entry* m_pNext; __int16 m_Depth; __int16 m_Counter; }; }; Header m_Header; public: LowLockStack() { m_Header.m_pNext = NULL; m_Header.m_Depth = 0; m_Header.m_Counter = 0; } ~LowLockStack() { } void PushEntry( T* pData ) { Entry* pEntry = new Entry; pEntry->pData = pData; Header header; Header xchg; do { xchg.m_XChg = m_Header.m_XChg; header.m_pNext = pEntry; header.m_Depth = xchg.m_Depth + 1; header.m_Counter = xchg.m_Counter + 1; pEntry->pNext = xchg.m_pNext; } while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg ); } T* PopEntry() { Entry* pEntry = NULL; Header header; Header xchg; do { xchg.m_XChg = m_Header.m_XChg; pEntry = xchg.m_pNext; if ( pEntry == NULL ) { return NULL; } header.m_pNext = pEntry->pNext; header.m_Depth = xchg.m_Depth - 1; } while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg ); T* pRet = pEntry->pData; delete pEntry; return pRet; } __int32 GetDepth() { return m_Header.m_Depth; } }; #endif \ifndef\uu LOW\u LOCK\u STACK\u H_ #定义低锁定堆栈_ 模板类低位堆栈 { 受保护的: 结构条目 { 条目*pNext; T*pData; }; 联管节头 { __int64 m_XChg; 结构 { 条目*m_pNext; __16米深; __INT16M_计数器; }; }; 标题m_标题; 公众: LowLockStack() { m_Header.m_pNext=NULL; m_收割台。m_深度=0; m_头.m_计数器=0; } ~LowLockStack() { } 无效输入(T*pData) { 分录*pEntry=新分录; pEntry->pData=pData; 收割台; 头部xchg; 做 { xchg.m_xchg=m_Header.m_xchg; header.m_pNext=pEntry; 收割台深度=xchg.m_深度+1; header.m_计数器=xchg.m_计数器+1; pEntry->pNext=xchg.m_pNext; }而(_interloctedcompareeexchange64(&m_Header.m_XChg,Header.m_XChg,XChg.m_XChg)!=XChg.m_XChg); } T*PopEntry() { 条目*pEntry=NULL; 收割台; 头部xchg; 做 { xchg.m_xchg=m_Header.m_xchg; pEntry=xchg.m_pNext; if(pEntry==NULL) { 返回NULL; } header.m_pNext=pEntry->pNext; 收割台深度=xchg.m_深度-1; }而(_interloctedcompareeexchange64(&m_Header.m_XChg,Header.m_XChg,XChg.m_XChg)!=XChg.m_XChg); T*pRet=pEntry->pData; 删除pEntry; 返回pRet; } __int32 GetDepth() { 返回m_标题。m_深度; } }; #恩迪夫

有人能帮我找出低锁列表中的错误吗? 我在Windows 32位上用C++编写了一个低锁列表。与使用关键部分相比,我有了很大的改进,但我希望有人检查我所做的是否正确,以及我所做的是否有任何错误: #ifndef __LOW_LOCK_STACK_H_ #define __LOW_LOCK_STACK_H_ template< class T > class LowLockStack { protected: struct Entry { Entry* pNext; T* pData; }; union Header { __int64 m_XChg; struct { Entry* m_pNext; __int16 m_Depth; __int16 m_Counter; }; }; Header m_Header; public: LowLockStack() { m_Header.m_pNext = NULL; m_Header.m_Depth = 0; m_Header.m_Counter = 0; } ~LowLockStack() { } void PushEntry( T* pData ) { Entry* pEntry = new Entry; pEntry->pData = pData; Header header; Header xchg; do { xchg.m_XChg = m_Header.m_XChg; header.m_pNext = pEntry; header.m_Depth = xchg.m_Depth + 1; header.m_Counter = xchg.m_Counter + 1; pEntry->pNext = xchg.m_pNext; } while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg ); } T* PopEntry() { Entry* pEntry = NULL; Header header; Header xchg; do { xchg.m_XChg = m_Header.m_XChg; pEntry = xchg.m_pNext; if ( pEntry == NULL ) { return NULL; } header.m_pNext = pEntry->pNext; header.m_Depth = xchg.m_Depth - 1; } while( _InterlockedCompareExchange64( &m_Header.m_XChg, header.m_XChg, xchg.m_XChg ) != xchg.m_XChg ); T* pRet = pEntry->pData; delete pEntry; return pRet; } __int32 GetDepth() { return m_Header.m_Depth; } }; #endif \ifndef\uu LOW\u LOCK\u STACK\u H_ #定义低锁定堆栈_ 模板类低位堆栈 { 受保护的: 结构条目 { 条目*pNext; T*pData; }; 联管节头 { __int64 m_XChg; 结构 { 条目*m_pNext; __16米深; __INT16M_计数器; }; }; 标题m_标题; 公众: LowLockStack() { m_Header.m_pNext=NULL; m_收割台。m_深度=0; m_头.m_计数器=0; } ~LowLockStack() { } 无效输入(T*pData) { 分录*pEntry=新分录; pEntry->pData=pData; 收割台; 头部xchg; 做 { xchg.m_xchg=m_Header.m_xchg; header.m_pNext=pEntry; 收割台深度=xchg.m_深度+1; header.m_计数器=xchg.m_计数器+1; pEntry->pNext=xchg.m_pNext; }而(_interloctedcompareeexchange64(&m_Header.m_XChg,Header.m_XChg,XChg.m_XChg)!=XChg.m_XChg); } T*PopEntry() { 条目*pEntry=NULL; 收割台; 头部xchg; 做 { xchg.m_xchg=m_Header.m_xchg; pEntry=xchg.m_pNext; if(pEntry==NULL) { 返回NULL; } header.m_pNext=pEntry->pNext; 收割台深度=xchg.m_深度-1; }而(_interloctedcompareeexchange64(&m_Header.m_XChg,Header.m_XChg,XChg.m_XChg)!=XChg.m_XChg); T*pRet=pEntry->pData; 删除pEntry; 返回pRet; } __int32 GetDepth() { 返回m_标题。m_深度; } }; #恩迪夫,c++,winapi,stack,interlocked,C++,Winapi,Stack,Interlocked,如果没有错误(我怀疑;),那么将其视为一个参考实现:D 编辑:考虑到一些批评,我更新了代码 您不同步对列表头成员的访问。这至少在两个层面上是不好的: 为列表标题赋值可能不像您想象的那样原子化。这意味着非同步读取操作可能会获得损坏的值 另一个更可能的问题是,如果您的机器有多个内核,那么每个内核都可以在处理器缓存中拥有自己的值副本。要使它们同步值,您需要一个内存屏障 正如您所发现的,无锁编程很难做到正确 Windows已经支持无锁单链表,您应该尝试使用它,而不是自己滚动。最明显的错误是您给它起的名

如果没有错误(我怀疑;),那么将其视为一个参考实现:D


编辑:考虑到一些批评,我更新了代码

您不同步对列表头成员的访问。这至少在两个层面上是不好的:

  • 为列表标题赋值可能不像您想象的那样原子化。这意味着非同步读取操作可能会获得损坏的值

  • 另一个更可能的问题是,如果您的机器有多个内核,那么每个内核都可以在处理器缓存中拥有自己的值副本。要使它们同步值,您需要一个内存屏障


正如您所发现的,无锁编程很难做到正确


Windows已经支持无锁单链表,您应该尝试使用它,而不是自己滚动。

最明显的错误是您给它起的名字。不管您将其实现为一个链表,您实现的都是一个堆栈。

考虑一下,当列表(堆栈)中有两个项目a和B时,下面的事件序列会发生什么,如
head->a->B
count
为2:

  • 线程1启动
    pop()
    调用,但在
    \u InterlocatedCompareeExchange64()之前被抢占
    
  • 线程2从堆栈中删除两个项目A和B,然后将两个新项目放回堆栈,顶部的项目恰好分配在与A相同的地址,因此我们有,比如
    head->A->D
    。请注意,
    计数回到2
    
  • 线程1恢复并成功执行CAS(
    \u InterlockedCompareeExchange64()
    )。现在
    head
    指向B,B被解除分配(坏),D丢失(坏)。 这是一部经典作品。您应该使用第二个单词作为生成编号,而不是项目计数,即永远不要减少它。

    现在有一个关于实验图书馆的邮件列表。


    另请看一看-这是一种不同的方法,其中虚拟节点可以防止生产者和消费者相互踩踏。

    InterlocatedCompareeExchange 64提供了一个内存屏障。这比看起来更糟糕-内存屏障是一个昂贵的操作,此实现将具有O(n)对于包含n个元素的列表,它们通常没有逃逸的内存障碍。一个使用锁的实现,即使在没有争用的情况下,仍然会有内存障碍(如果锁没有提供障碍,它们将是无用的。)这是绝对的-但是你不必有这么多。我想每次通话一次应该足够理想,每次通话一次。只有在获取数据后但在交换之前更改了头节点时,才会进行重试。您能否量化在关键部分看到的性能增益?访问列表的权限有多大?有很多方法可以获得比无锁更好的性能(例如,每线程队列)?我没有做足够的测试来量化它。我能说的是,使用CriticalSections会降低性能,因为我在这个问题上抛出了更多线程。事实上,单线程提供了迄今为止最好的性能。在新系统中,代码的线程部分从大约0.6秒减少到了大约0.2秒(当拆分为4个线程时)。我相信你会同意,这不是完美的,但比旧系统有了很大的改进。当然,由于每个任务的执行速度,争用问题是显而易见的。我不知道对12个特性的16384个MFCC进行日志测试的速度会有现在这么快。旧代码花了绝大多数时间争夺锁。显然,对于运行较慢的任务,争用会更少……不,我完全知道这一点。但我这么做的原因是,我可以很容易地为其他平台重新实现。。。是m