std::list 中无锁的并行追加和迭代
Parallel append and iteration without locks in std::list
我在多线程程序中使用 std::list。元素只添加到列表的末尾,只从列表的开头删除。
存在一个写锁来保证写互斥。读者在不获取锁的情况下访问链表。读者维护不能被 erase() 无效的迭代器,因为我保证元素只有在读者传递它们时才会被删除。我能想象的唯一可能的数据竞争是,如果附加了一个元素,并且其中一位读者在插入者写入元素本身之前访问了该元素。
对于单个写入器,附加(在末尾插入)应该是原子的,因为插入新元素需要单个写入。
std::list 显然不提供任何保证,有人可以确认上述用法应该在没有数据竞争的情况下工作。如果没有,是否有提供这种保证的替代方案(例如 boost)?
如您所写,可能会出现竞争条件:
The only possible data race I can imagine is if an element is appended, and one of the readers accesses that element before the inserter has written the element itself.
另外 std::list 是一个 doubly-linked list,因此在删除第一个元素时会访问第二个元素,而在添加新元素时会写入旧的最后一个元素。所以你的迭代器必须是常量(没有 ++iter 或 --iter)。
您可能想看看 boost::lockfree::queue — 它可能正是您要找的。
我使用 boost::intrusive::list 解决了禁用大小计数器时的问题,同时删除和插入元素时变得不一致。如果没有这个,boost 列表会设置四个指针,而当 removing/inserting 元素是我需要的时,什么也没有。
我在多线程程序中使用 std::list。元素只添加到列表的末尾,只从列表的开头删除。 存在一个写锁来保证写互斥。读者在不获取锁的情况下访问链表。读者维护不能被 erase() 无效的迭代器,因为我保证元素只有在读者传递它们时才会被删除。我能想象的唯一可能的数据竞争是,如果附加了一个元素,并且其中一位读者在插入者写入元素本身之前访问了该元素。
对于单个写入器,附加(在末尾插入)应该是原子的,因为插入新元素需要单个写入。
std::list 显然不提供任何保证,有人可以确认上述用法应该在没有数据竞争的情况下工作。如果没有,是否有提供这种保证的替代方案(例如 boost)?
如您所写,可能会出现竞争条件:
The only possible data race I can imagine is if an element is appended, and one of the readers accesses that element before the inserter has written the element itself.
另外 std::list 是一个 doubly-linked list,因此在删除第一个元素时会访问第二个元素,而在添加新元素时会写入旧的最后一个元素。所以你的迭代器必须是常量(没有 ++iter 或 --iter)。
您可能想看看 boost::lockfree::queue — 它可能正是您要找的。
我使用 boost::intrusive::list 解决了禁用大小计数器时的问题,同时删除和插入元素时变得不一致。如果没有这个,boost 列表会设置四个指针,而当 removing/inserting 元素是我需要的时,什么也没有。