你能更清楚地澄清这一点吗?
那是一个涉及很多话题的密集段落。您具体要求澄清哪个或哪些主题?你的问题太宽泛了,无法令人满意地回答。对不起。
现在,如果您的问题是针对非竞争同步的,这意味着 JVM 中的线程不必阻塞、解除阻塞/通知然后回到阻塞状态。
在底层,JVM 使用硬件特定的内存屏障来确保
- 始终从
volatile
主内存读取和写入字段,而不是从 CPU/核心缓存读取和写入字段,并且
- 您的线程不会阻止/解除阻止来访问它。
没有争议。当您使用同步块 OTH 时,您的所有线程都处于阻塞状态,除了一个线程读取同步块保护的任何数据。
让我们调用那个线程,即访问同步数据的线程 A。
现在,这里是关键,当线程 A处理完数据并存在同步块时,这会导致 JVM唤醒所有其他正在/正在等待线程 A退出同步块的线程。
他们都醒来了(这在 CPU/内存方面很昂贵)。他们都竞相试图获得同步块。
想象一下一大群人试图通过一个小房间离开拥挤的房间。是的,就像那样,这就是线程在尝试获取同步锁时的行为方式。
但只有一个人得到它并进入。所有其他人都回到睡眠状态,有点像所谓的阻塞状态。这也是昂贵的,资源方面的。
因此,每当其中一个线程存在同步块时,所有其他线程都会发疯(我能想到的最佳心理形象)来访问它,一个得到它,然后所有其他线程都回到阻塞状态。
这就是使同步块变得昂贵的原因。现在,请注意:在 JDK 1.4 之前,它曾经非常昂贵。那是17年前的事了。Java 1.4 开始出现一些改进(2003 IIRC)。
然后 Java 1.5 在 12 年前的 2005 年引入了更大的改进,这使得同步块的成本更低。
记住这些事情很重要。那里有很多过时的信息。
如果我有大量线程读取 volaile 变量怎么办?
就正确性而言,这并不重要。无论线程数如何,字段将volatile
始终显示一致的值。
现在,如果您有大量线程,性能可能会因为上下文切换、内存利用率等而受到影响(不一定和/或主要是因为访问volatile
字段。
你能提供争用定义吗?
请不要误会,但如果你问这个问题,恐怕你还没有完全准备好使用你正在阅读的那本书。
您将需要对并发和争用进行更基本的介绍。
https://en.wikipedia.org/wiki/Resource_contention
此致。