java - 为什么 volatile 读总是无竞争的?

标签 java concurrency locking volatile contention

引用自《java并发实践》一书:

The performance cost of synchronization comes from several sources. The visibility guarantees provided by synchronized and volatile may entail using special instructions called memory barriers that can flush or invalidate caches, flush hardware write buffers, and stall execution pipelines. Memory barriers may also have indirect performance consequences because they inhibit other compiler optimizations; most operations cannot be reordered with memory barriers. When assessing the performance impact of synchronization, it is important to distinguish between contended and uncontended synchronization. The synchronized mechanism is optimized for the uncontended case (volatile is always uncontended), and at this writing, the performance cost of a "fastͲpath" uncontended synchronization ranges from 20 to 250 clock cycles for most systems.

你能把这个说得更清楚吗? 如果我有大量读取 volaile 变量的线程怎么办?

您能提供争用定义吗?

是否有工具可以衡量争用?它以哪些值来衡量?

最佳答案

Can you clarify this more clear?

这是一个涉及很多主题的密集段落。您具体要求澄清哪些主题?你的问题太宽泛,无法令人满意地回答。抱歉。

现在,如果您的问题特定于无竞争同步,则意味着 JVM 中的线程不必阻塞、解除阻塞/通知,然后返回阻塞状态。

在底层,JVM 使用特定于硬件的内存屏障来确保

  1. volatile 字段始终从主内存读取和写入,而不是从CPU/核心缓存读取和写入,并且
  2. 您的线程不会阻止/取消阻止对其进行访问。

没有争用。当您使用同步块(synchronized block) OTH 时,所有线程都处于阻塞状态,除了一个线程(读取受同步块(synchronized block)保护的任何数据的线程)。

我们将该线程(访问同步数据的线程)称为线程 A。

现在,关键是,当线程 A 处理完数据并存在同步块(synchronized block)时,这会导致 JVM唤醒 所有其他线程正在等待线程 A 退出同步块(synchronized block)。

它们都会醒来(这对于 CPU/内存来说是昂贵的)。他们都在竞相争夺同步块(synchronized block)。

想象一下一群人试图通过一个小房间离开拥挤的房间。是的,就像这样,这就是线程尝试获取同步锁时的行为方式。

但只有一个得到它并进入。所有其他人都会重新进入休眠状态,处于所谓的“阻塞状态”。从资源角度来看,这也是昂贵的。

因此,每当其中一个线程存在同步块(synchronized block)时,所有其他线程就会疯狂(我能想到的最好的心理图像)来访问它,其中一个线程获得了它,而所有其他线程都回到阻塞状态.

这就是同步块(synchronized block)昂贵的原因。现在,需要注意的是:在 JDK 1.4 之前它曾经非常昂贵。那是17年前的事了。 Java 1.4 开始出现一些改进(2003 IIRC)。

然后,Java 1.5 在 12 年前的 2005 年引入了更大的改进,这使得同步块(synchronized block)变得更便宜。

记住这些事情很重要。那里有很多过时的信息。

What if I have huge amount threads which read volaile variable ?

就正确性而言,这并不重要。无论线程数量如何, volatile 字段将始终显示一致的值。

现在,如果您有大量线程,性能可能会因为上下文切换、内存利用率等而受到影响(不一定和/或主要是因为访问 volatile 字段。

Can you provide contention definition?

请不要误解,但如果您问这个问题,恐怕您还没有完全准备好使用您正在阅读的这本书。

您将需要对并发性和争用进行更基本的介绍。

https://en.wikipedia.org/wiki/Resource_contention

致以诚挚的问候。

关于java - 为什么 volatile 读总是无竞争的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42626558/

相关文章:

java - 同步方法中的重入

java - ANT + propertyregex 问题

concurrency - 在 golang 中创建同步列表

c - SQLite3 和多进程

c++ - 在 C++ 中获取一个只有一次有效的锁

ios - 如何在 iOS 上使用 swift 防止应用程序屏幕锁定

java - 类扩展抽象类实现接口(interface)

java - Collections.sort 不起作用

java - J2ME的append()方法

http - 同时写入和读取 map 会导致潜在的竞争条件