同步对象是否可缓存?
Are synchronization objects cacheable?
我是多线程世界的新手,并开始进入它。我发现线程化需要同步。易失性不再是一个可靠的东西。我想知道如果同步对象是可缓存的编译器或在任何阶段?
使用平台/语言:c++, win32, Windows
在c++中,volatile关键字用于cpu无法缓存的对象。但是今天的编译器并不严格遵循这一点。是否有其他方法可以使同步对象不可缓存(或者没有对这些对象应用其他优化)
tl;dr:同步对象是否可缓存?如果是,如何使它不可缓存?
我不确定我是否遵循您的问题:编译器缓存几乎与多线程无关。编译器缓存唯一能做的就是通过缓存以前的编译来提高编译速度。
同步对象可以被"缓存",因为它们是您决定用于同步的任意对象,但这对并发性几乎没有影响。在同步时,您需要关心的唯一一件事是,当您有多个线程争用一个资源时,它们必须在同一个对象上同步,以便对资源进行读/写访问。
根据您提到的volatile,我将大胆猜测一下,并假设您担心同步对象可能缓存在线程的本地缓存中,并且一个线程对同步对象的更改可能对另一个线程不可见。然而,这是一个有缺陷的想法:- 当你调用lock()或synchronize()(取决于语言)时,你所需要关心的是锁是在同一个对象上执行的,而不管对象的内部状态如何。
- 一旦你获得了一个对象上的锁,你在这个锁范围内修改的任何资源都只能被一个线程修改。
一般来说,您应该使用不会更改的同步对象(理想情况下是readonly、const或final),我们在这里只讨论引用,而不是对象本身的内容。下面是一个例子:
object sync = new object();String something = "hello":
空白ModifySomething (){sync = new object();//<——你不应该这样做!!锁(同步){something = GenerateRandomString();}}
现在请注意,每次线程调用ModifySomething
时,同步对象将被一个新对象替换,并且线程永远不会在同一个对象上同步,因此可能并发写something
。
如果不指定运行时环境,这个问题就没有多大意义。
在Java的情况下,例如,同步对象(用于同步的对象)就像任何其他对象一样。对象是同步的目标,因此只有当包含同步对象的变量可以更改时,才需要volatile
(适用于成员变量)。我将避免需要这种构造的程序设计。
记住(同样是在Java中),是表达式的求值——通常是变量访问——导致要使用的同步对象。在这方面,这个计算和其他的没有什么不同。
然而,在一天结束时,它只是以一种定义良好且行为良好的方式使用特定运行时/环境的同步工具。幸福的编码。
例如,Java保证
synchronized(x) { foo }
(其中x是一个特定的对象)将创建一个互斥的关键区域,在这个关键区域中执行foo
。要做到这一点,它必须进行内部工作,以确保在所有处理器/缓存中正确刷新簿记数据。然而,就使用同步构造而言,这些细节通常超出了运行时的范围。
同步对象必须由操作系统管理,操作系统还管理线程和缓存。因此,处理缓存是操作系统的责任。如果它知道一个同步对象只在一个CPU上使用(例如,因为它没有分配第二个CPU给你的进程),操作系统很可能决定将同步对象保留在第一个CPU的缓存中。如果它需要跨CPU共享,那么也会发生。
一个实际的结果是,您将始终初始化同步对象。在c++中,这是很自然的(构造函数会处理这个问题),但在其他语言中,您必须显式地这样做。操作系统必须跟踪同步对象
- 存储指令是否会阻止缓存未命中的后续指令?
- 空函数的参数是否加载到缓存中?
- 是否可以检查变量是否位于 L1/L2/L3 缓存中
- dynamic_cast每次调用是否比具有空检查的缓存变量更昂贵?
- gcc 中的多个对齐属性是否可以用于保证缓存行分隔?
- 使用 redis 进行日志缓存:是否可以创建逐出到 PostgreSQL 的逐出策略?
- std::array 在存储大型对象时是否仍然对缓存友好?
- 有没有办法检查内存缓存是否已重新启动?
- 是否有用于可视化缓存的工具C++
- 三元运算符缓存是否不友好
- getenv 是否缓存结果
- CPU 缓存是否也从以前的内存位置加载信息
- 基于范围的 for 循环是否缓存容器表达式,或每次迭代重新计算它
- 我可以检查内存块(例如,使用 malloc 分配)是否保留在缓存中吗?
- volatile限定符是否取消此内存的缓存
- OOP是否鼓励良好的缓存,从而提高性能
- std::map是否支持缓存?
- 如何确定地址是否与缓存对齐
- shared_ptrs是否会遇到由于引用计数器原子递增/递减而导致的缓存丢失?
- 频繁执行的表达式是否会缓存其结果