- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
boost::shared_mutex
或 std::shared_mutex
(C++17) 可用于单个写入器、多个读取器访问。作为一项教育练习,我整理了一个使用自旋锁并具有其他限制(例如公平策略)的简单实现,但显然不打算在实际应用程序中使用。
这个想法是互斥锁保持一个引用计数,如果没有线程持有锁,该引用计数为零。如果 > 0,则该值表示具有访问权限的读者数。如果为 -1,则表示单个作者具有访问权限。
这是没有数据竞争的正确实现(特别是使用的最小内存排序)吗?
#include <atomic>
class my_shared_mutex {
std::atomic<int> refcount{0};
public:
void lock() // write lock
{
int val;
do {
val = 0; // Can only take a write lock when refcount == 0
} while (!refcount.compare_exchange_weak(val, -1, std::memory_order_acquire));
// can memory_order_relaxed be used if only a single thread takes write locks ?
}
void unlock() // write unlock
{
refcount.store(0, std::memory_order_release);
}
void lock_shared() // read lock
{
int val;
do {
do {
val = refcount.load(std::memory_order_relaxed);
} while (val == -1); // spinning until the write lock is released
} while (!refcount.compare_exchange_weak(val, val+1, std::memory_order_acquire));
}
void unlock_shared() // read unlock
{
// This must be a release operation (see answer)
refcount.fetch_sub(1, std::memory_order_relaxed);
}
};
最佳答案
(CAS = Compare And Swap = C++ compare_exchange_weak
函数,在 x86 上通常会编译为 x86 lock cmpxchg
instruction,只有当它拥有 Exclusive 或 Modified MESI 中的缓存行时才能运行状态)。
lock_shared
看起来不错:旋转只读只在看起来可能时尝试 CAS 比在 CAS 或原子增量上旋转更能提高性能。您已经需要执行只读检查以避免将 -1
更改为 0
并解锁写锁。
在 x86 上,在自旋循环的重试路径中放置一个 _mm_pause()
以避免在退出只读自旋循环时内存顺序错误推测管道核弹,并从中窃取更少的资源另一个超线程在旋转时。 (使用 while()
循环,而不是 do{}while()
,因此暂停仅在失败一次后运行。Skylake 上的 pause
和稍后等待大约 100 个周期,因此请避免在快速路径中使用它。)
我认为 unlock_shared
应该使用 mo_release
,而不是 mo_relaxed
,因为它需要从共享数据结构,以确保编写器不会在读取器临界区加载发生之前开始写入。 (LoadStore reordering 是弱排序架构上的一个东西,即使 x86 只执行 StoreLoad 重新排序。)A Release operation will order preceding loads and keep them inside the critical section .
(in write
lock
): // can memory_order_relaxed be used if only a single thread takes write locks ?
不,您仍然需要将写入保留在临界区内,因此 CAS 仍然需要与来自 unlock_shared
的(用 C++ 术语)释放存储同步。
https://preshing.com/20120913/acquire-and-release-semantics/有一张漂亮的图片,显示了发布存储或获取加载的单向屏障效应。
关于C++ shared_mutex 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41193648/
这真的很奇怪。首先,我不知道您可以删除函数,其次,这发生在外部库中。 错误的情况是我正在使用 QtCreator 构建项目并一起 boost ,没有任何静态库。 使用的编译器是gcc myprogra
我正在尝试编写一个允许多个读者或一个作者访问数据的类。问题是读者可以有条件地成为作家,我想确保无论有多少线程想成为作家,只允许一个,其他线程等待作家完成并变回读者。 问题出在 if(condition
我的印象是,如果获取了太多共享锁,使用 c++17 的 std::shared_mutex 实现的多读/单写模式可能永远不会放弃唯一锁。 在 cppreference 上挖掘之后,我不确定情况是否如此
boost::shared_mutex 或 std::shared_mutex (C++17) 可用于单个写入器、多个读取器访问。作为一项教育练习,我整理了一个使用自旋锁并具有其他限制(例如公平策略)
我有一个小型模板类,它有一个 boost::shared_mutex 类型的非静态成员。每当我尝试编译它时,我都会收到错误: “boost::shared_mutex::shared_mutex”:无
我想将 shared_mutex 与共享/唯一锁一起用于读/写。 现在如果我有 2 个对象并且我希望它们使用相同的锁,我可以将第一个互斥锁的值分配给第二个互斥锁吗? 还是我必须创建一个指向 share
我有一个有几个读者和几个作家的类(class)。我想使用读/写锁(使用shared_mutex) 有关此锁的所有示例和信息,在同一个函数中使用和释放锁: std::shared_mutex 我想以这种
从 C++17(C++14) 开始,我们有了 std::shared_(timed_)mutex 类。很长一段时间以来,Qt 都有一个类似的类 QReadWriteLock。 QReadWriteLo
似乎 Boost 的 shared_mutex 是非递归的.. 周围有吗? (没有重新实现整个东西) 最佳答案 看看this thread这个excellent explanation为什么 shar
我在这个帖子中找到了 HowardHinnant 的答案。 C++11 equivalent to boost shared_mutex 不幸的是,它似乎使用了 Microsoft 编译器 (VS20
C++17 引入了 std::shared_mutex 类型。我一直在查看 CppReference 上的文档对产生未定义行为的情况特别感兴趣。 在通读两种解锁方法(一种用于释放独占所有权,一种用于释
我正在尝试使用 boost::shared_mutex 来实现多读取器/单写入器互斥锁。我的问题很简单,当另一个线程试图锁定该 shared_mutex 以进行写入时,一个线程是否有可能获得对 sha
C++17 引入了 std::shared_mutex 和 std::scoped_lock。我现在的问题是,当它作为参数传递时,scoped_lock 将始终以独占(写入器)模式锁定共享互斥锁,而不
boost::shared_mutex 是否有 C++11 等效项。或者在 C++11 中处理多读/单写情况的另一种解决方案? 最佳答案 我尝试过但未能将 shared_mutex 导入 C++11。
我有许多对象,每个对象都与一个 boost::shared_mutex 相关联(我需要共享/唯一锁功能)。 在代码中的某些场合,我需要一次获得多个对象的唯一所有权。 for (FileMetaData
通常,当使用“普通”互斥量时,您会像在 remove1() 中那样使用它。但是,现在有了 shared_lock 和 unique_lock,是否应该先使用共享锁,只有在必要时才使用唯一锁?请注意,当
查看C++ compiler support , 看来 std::shared_mutex 的未计时版本在 GCC 5.0+ 中可用。但是,即使使用 gcc version 5.3.0 2015120
我有一个多线程应用程序,它必须经常读取一些数据,并且偶尔会更新这些数据。现在,互斥锁可以安全地访问该数据,但它很昂贵,因为我希望多个线程能够同时读取,并且仅在需要更新时将它们锁定(更新线程可以等待其他
你有关于这个主题的任何信息吗?特别是 boost::shared_mutex 和读写器互斥体有什么问题吗? 读写器互斥体可能被滥用,例如即使与简单的互斥体相比,频繁的写入器锁定也会降低性能。但在很多情
嗨,Boost 爱好者们 我们遇到了 shared_mutex 的问题,并一直在深入研究 boost 源。我们无法判断这是否是一个死锁情况,或者我们只是不理解共享的读/写锁的互斥实现。 应用: 我们有
我是一名优秀的程序员,十分优秀!