- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
一般来说,加载-获取/存储-释放同步是 C++11 内存模型中最常见的基于内存排序的同步形式之一。这基本上就是互斥锁提供内存排序的方式。加载获取和存储释放之间的“关键部分”始终在不同的观察者线程之间同步,因为所有观察者线程将就获取之后和释放之前发生的事情达成一致。
通常,这是通过读取-修改-写入指令(如比较交换)以及获取屏障来实现的,当进入临界区时,以及在退出临界区时另一个带有释放屏障的读取-修改-写入指令部分。
但在某些情况下,加载获取和发布存储之间可能有类似的临界区[1],只是只有一个线程实际修改了同步变量。其他线程可能读取同步变量,但实际上只有一个线程修改它。在这种情况下,进入临界区时,不需要读-修改-写指令。您只需要一个简单的存储,因为您不会与其他试图修改同步标志的线程竞争。 (这可能看起来很奇怪,但请注意许多无锁内存回收延迟模式,如用户空间 RCU 或基于纪元的回收,使用仅由一个线程写入但由多个线程读取的线程局部同步变量,因此这种情况并不太奇怪。)
所以,当进入临界区时,你可以这样做:
sync_var.store(true, ...);
.... critical section ....
sync_var.store(false, std::memory_order_release);
没有竞争,因为再次强调,当只有一个线程需要设置/取消设置临界区变量时,不需要读取-修改-写入。其他线程可以简单地通过加载获取来读取临界区变量。
问题是,当您进入临界区时,您需要一个acquire 操作 或fence。但是你不需要做一个LOAD,只需要一个STORE。那么,当您真正只需要一个 STORE 时,什么是产生获取订单的好方法呢?我只看到两个真正的选项属于 C++ 内存模型。要么:
exchange
而不是商店,因此您可以执行 sync_var.exchange(true, std::memory_order_acquire)
。这里的缺点是交换是一个更重量级的读取-修改-写入操作,而您真正需要的只是一个简单的存储。插入一个“虚拟”加载获取,例如:
(void)sync_var.load(std::memory_order_acquire);sync_var.store(true, std::memory_order_relaxed);
“虚拟”加载获取似乎更好。据推测,编译器无法优化掉未使用的负载,因为这是一条原子指令,其副作用是与 sync_var
上的释放操作产生“同步”关系。但它看起来也很老套,如果没有评论解释发生了什么,意图就不清楚了。
那么当我们只需要一个简单的存储时,产生获取语义的最佳方法是什么?
[1] 我随意使用术语“临界区”。我不一定是指始终通过互斥访问的部分。相反,我只是指通过获取-释放语义同步内存排序的任何部分。这可能指的是互斥量,也可能只是指 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
)。
关于c++ - 线程本地获取/释放同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49635697/
我有一个附加了 View Controller 的 AVAudioPlayer 实例。 @property (nonatomic, retain) AVAudioPlayer *previewAudi
我是java初学者。假设我声明了一个 Account 类型的变量 Account _account = new Account("Thomas"); 然后在其他地方我做了这样的事情: _account
我在我的应用程序中使用了 3 个 UIViewController,现在我想知道当我从另一个应用程序切换到另一个 UIViewController 时释放它们是否是一个好主意。显然,这将是隐藏的,当它
我分配了一个直接缓冲区: ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024); 我读过: Deallocating Direct Buf
场景。我有一个图表,我可以使用右键单击来执行平移。这非常有效。然后我完美地添加了右键菜单。 问题。现在,即使在拖动操作完成后释放鼠标,也会显示右键菜单。 有没有办法在 Java Swing 或 Jav
我使用此代码获取 ABPerson 的姓氏 CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABP
目前,我们在基于 C 的嵌入式应用程序中使用 malloc/free Linux 命令进行内存分配/取消分配。我听说这会导致内存碎片,因为内存分配/取消分配会导致堆大小增加/减少,从而导致性能下降。其
当我尝试释放缓冲区时遇到问题。每次我尝试将缓冲区传递给释放方法时,都会发生段错误。 Valgrind 确认段错误位于 BufferDeallocate 方法中。 ==30960== Memcheck,
我想知道何时按下或释放修改后的键(Ctrl 或 Shift)。 基本上,用户可以在按下修改键的情况下执行多次击键,而我不想在它被释放之前执行一个操作(想想 Emacs 和 Ctrl + X + S).
我编写了一个相当大的网络应用程序。它运行良好一段时间,然后慢慢开始运行缓慢,因为 DOM 节点开始爬升到 80,000 - 100,000 左右。 所以我一直在 Chrome 开发工具控制台 (DCT
我知道在像 c 这样的语言中,我需要在分配内存后释放它。 (我来自 Java),对此我有几个问题: 当我在做的时候: int array[30]; (即创建一个大小为 30 个整数的数组)与
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: How to release pointer from boost::shared_ptr? Detach
我有一个可以从多个后台线程访问的类,可能同时访问。我无法复制该类,因为重新创建它的内容(处理或内存方面)可能很昂贵。 也有可能在后台处理仍在继续并访问该属性时替换了此类的属性。 目前我有定期的保留/释
这个问题是对: 的扩展链接-1:Creating an image out of the ios surface and saving it Link-2:Taking Screenshots fro
我有一个实例变量 NSMutableArray* searchResults。 首先,我初始化它: self.searchResults = [[NSMutableArray alloc] init]
如果我在堆上声明一些东西,比如 char *a=new char[1000] 并且主程序停止,如果没有 delete[]<,那么分配的内存会发生什么 调用?它保留在堆上还是自动释放? 最佳答案 就C+
在开发相机应用时,我遇到了一个异常,该异常仅在我切换到其他应用时发生(onPause() 用于我的应用)。 01-15 17:22:15.017: E/AndroidRuntime(14336): F
使用 JDK 1.8 编译时出现 maven 编译器错误 无法执行目标 org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (de
将 BufferedImage 保存到磁盘(以释放内存)的最快方法是什么? 我的 Java 应用程序处理大量图像(每约 300 毫秒将图像加载到内存中)。大多数这些图像都会立即被丢弃 (gc),但每隔
使用 JDK 1.8 编译时出现 maven 编译器错误 未能在项目 DUMMY 上执行目标 org.apache.maven.plugins:maven-compiler-plugin:3.8.1:
我是一名优秀的程序员,十分优秀!