繁体   English   中英

线程本地获取/释放同步

[英]Thread-local acquire/release synchronization

通常,load-acquire / store-release同步是C ++ 11内存模型中最常见的基于内存排序的同步形式之一。 它基本上是互斥体提供内存排序的方式。 负载获取和存储释放之间的“关键部分”总是在不同的观察者线程之间同步,因为所有观察者线程都会同意获取之后和发布之前发生的事情。

通常,这是通过读取 - 修改 - 写入指令(如比较交换)以及进入临界区时的获取屏障以及退出临界区时具有释放屏障的另一个读取 - 修改 - 写入指令来实现的。

但是在某些情况下,您可能在load-acquire和release-store之间有一个类似的关键部分 [1],除了只有一个线程实际修改了同步变量。 其他线程可能会读取同步变量,但只有一个线程实际修改它。 在这种情况下,进入临界区时,不需要读 - 修改 - 写指令。 您只需要一个简单的商店,因为您没有与试图修改同步标志的其他线程竞争。 (这可能看起来很奇怪,但请注意许多无锁内存回收延迟模式,如用户空间RCU或基于纪元的回收,使用线程本地同步变量,只能由一个线程写入,但由许多线程读取,所以这不是一种奇怪的情况。)

因此,当进入关键部分时,您可以执行以下操作:

sync_var.store(true, ...);

.... critical section ....

sync_var.store(false, std::memory_order_release);

没有竞争,因为当只有一个线程需要设置/取消设置临界区变量时,不需要进行读 - 修改 - 写。 其他线程可以通过load-acquire简单地读取临界区变量。

问题是,当您进入临界区时,您需要获取操作或围栏。 但是你不需要做一个LOAD,只需要一个STORE。 那么,当您真正需要商店时,制作获取订购的好方法是什么? 我看到只有两个真正的选项属于C ++内存模型。 或者:

  1. 使用exchange而不是商店,因此您可以执行sync_var.exchange(true, std::memory_order_acquire) 这里的缺点是,当你真正需要的只是一个简单的商店时,交换是一个更重量级的读 - 修改 - 写操作。
  2. 插入“虚拟”加载获取,如:

    (无效)sync_var.load(标准:: memory_order_acquire); sync_var.store(true,std :: memory_order_relaxed);

“虚拟”负载获取似乎更好。 据推测,编译器无法优化掉未使用的负载,因为它是一个原子指令,具有与sync_var上的释放操作产生“同步 - ”关系的sync_var 但它似乎也非常hacky,如果没有评论解释正在发生的事情,目的还不清楚。

那么,当我们需要做的只是一个简单的商店时,产生获取语义的最佳方法是什么?


[1]我松散地使用术语“临界区”。 我不一定是指通过互斥方式访问的部分。 相反,我只是指通过acquire-release语义同步内存排序的任何部分。 这可能是指互斥锁,或者它可能只是指RCU之类的东西,其中临界区可以由多个读者同时访问。

您的逻辑中的缺陷是不需要原子RMW,因为关键部分中的数据由单个线程修改,而所有其他线程仅具有读访问权限。
这不是真的; 在阅读和写作之间仍然需要有明确的顺序。 您不希望在另一个线程仍在读取数据时修改数据。 因此,每个线程在完成访问数据时都需要通知其他线程。

通过仅使用原子库来进入临界区,无法建立“同步 - 关系”关系。 获取/释放同步基于运行时关系,其中收集器仅在观察到原子负载返回的特定值之后才知道同步完成。 这是永远无法通过单个原子存储实现的,因为一个修改线程可以随时更改原子变量sync_var ,因此无法知道另一个线程是否仍在读取数据。

具有“虚拟” load/acquire的选项也是无效的,因为它无法通知其他线程它想要独占访问。 您尝试通过使用单个(宽松)存储来解决此问题,但是加载和存储是可以被其他线程中断的单独操作(即,多个线程同时访问关键区域)。

每个线程必须使用原子RMW来加载特定值,同时更新变量以通知它现在具有独占访问权的所有其他线程(无论是读取还是写入)。

void lock()
{
    while (sync_var.exchange(true, std::memory_order_acquire));
}

void unlock()
{
    sync_var.store(false, std::memory_order_release);
}

在多个线程同时具有读访问权限的情况下(例如, std::shared_mutex ),可以进行优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM