简体   繁体   English

为什么易失性读取始终无条件?

[英]Why volatile read always uncontended?

Quote from book java concurrency in practice: 在实践中引用书籍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. synchronized和volatile提供的可见性保证可能需要使用称为内存屏障的特殊指令,这些指令可以刷新或使缓存无效,刷新硬件写缓冲区和停止执行流水线。 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. 同步机制针对非竞争情况进行了优化( volatile始终是无竞争的 ),在撰写本文时,对于大多数系统,“fastͲpath”无竞争同步的性能成本范围为20到250个时钟周期。

Can you clarify this more clear? 你能更明确地澄清一下吗? What if I have huge amount threads which read volaile variable ? 如果我有大量的线程读取易变量怎么办?

Can you provide contention definition? 你能提供争用定义吗?

Is there tool to meausure contention? 对于meausure争用有工具吗? In which values it is measures? 它的衡量标准是哪些?

Can you clarify this more clear? 你能更明确地澄清一下吗?

That is one dense paragraph that touches a lot of topics. 这是一个涉及很多主题的密集段落。 Which topic or topics specifically are you asking for clarification? 您要求澄清哪些主题或主题? Your question is too broad to answer satisfactorily. 你的问题太宽泛,无法令人满意地回答。 Sorry. 抱歉。

Now, if you question is specific to uncontended synchronization, it means that threads within a JVM do not have to block, get unblocked/notified and then go back to a blocked state. 现在,如果您的问题特定于无竞争同步,则意味着JVM中的线程不必阻塞, 取消阻止/通知,然后返回阻塞状态。

Under the hood, the JVM uses hardware specific memory barriers that ensure 在引擎盖下,JVM使用硬件特定的内存屏障来确保

  1. A volatile field is always read and written to/from main memory, not from the CPU/core cache, and 始终从主存储器读取和写入volatile字段,而不是从CPU /核心高速缓存读取和写入
  2. Your thread will not block/unblock to access it. 您的线程不会阻止/取消阻止访问它。

There is no contention. 没有争论。 When you use a synchronized block OTH, all your threads are in a blocked state except one, the one reading whatever data is being protected by the synchronized block. 当您使用同步块OTH时,所有线程都处于阻塞状态,除了一个,读取同步块保护的数据。

Let's call that thread, the one accessing the synchronized data, thread A . 让我们调用该线程,即访问同步数据的线程线程A.

Now, here is the kicker, when thread A is done with the data and exists the synchronized block, this causes the JVM to wake up all the other threads that are/were waiting for thread A to exit the synchronization block. 现在,这里是踢球者,当线程A完成数据并且存在synchronized块时,这会导致JVM 唤醒等待线程A退出同步块的所有其他线程。

They all wake up (and that is expensive CPU/memory wise). 他们都醒了(这是昂贵的CPU /内存)。 And they all race trying to get a hold of the synchronization block. 他们都试图抓住同步块。

Imagine a whole bunch of people trying to exit a crowded room through a tiny room. 想象一下,一大群人试图通过一个小房间离开拥挤的房间。 Yep, like that, that's how threads act when they try to grab a synchronization lock. 是的,这就是线程在尝试获取同步锁时的行为方式。

But only one gets it and gets in. All the others go back to sleep, kind of, in what is called a blocked state . 但是只有一个人得到它并进入。所有其他人都回去睡觉,有点,在所谓的封锁状态 This is also expensive, resource wise. 资源方面,这也是昂贵的。

So every time one of the threads exists a synchronization block, all the other threads go crazy (best mental image I can think of) to get access to it, one gets it, and all the others go back to a blocked state. 因此,每当其中一个线程存在同步块时,所有其他线程就会疯狂(我能想到最好的心理图像)来访问它,一个获取它,所有其他线程都回到阻塞状态。

That's what makes synchronized blocks expensive. 这就是使同步块价格昂贵的原因。 Now, here is the caveat: It used to be very expensive pre JDK 1.4. 现在,这里有一个警告:它曾经是JDK 1.4之前非常昂贵的。 That's 17 years ago. 那是17年前的事了。 Java 1.4 started seeing some improvements (2003 IIRC). Java 1.4开始看到一些改进(2003 IIRC)。

Then Java 1.5 introduced even greater improvements in 2005, 12 years ago, which made synchronized blocks less expensive. 然后,Java 1.5在2005年,12年前引入了更大的改进,这使得同步块更便宜。

It is important to keep such things in mind. 记住这些事情很重要。 There is a lot of outdated information out there. 那里有很多过时的信息。

What if I have huge amount threads which read volaile variable ? 如果我有大量的线程读取易变量怎么办?

It wouldn't matter that much in terms of correctness. 在正确性方面,这并不重要。 A volatile field will always show a consistent value regardless of the number of threads. 无论线程数如何, volatile字段始终显示一致的值。

Now, if you have a very large number of threads, performance can suffer because of context switches, memory utilization, etc (and not necessarily and/or primarily because of accessing a volatile field. 现在,如果您拥有非常多的线程,性能可能因上下文切换,内存利用率等而受到影响(并且不一定和/或主要是因为访问volatile字段。

Can you provide contention definition? 你能提供争用定义吗?

Please don't take it the wrong way, but if you are asking that question, I'm afraid you are not fully prepared to use a book like the one you are reading. 请不要采取错误的方式,但如果你问这个问题,我担心你没有完全准备好使用像你正在阅读的那本书。

You will need a more basic introduction to concurrency, and contention specifically. 您将需要更具基本的并发性介绍和争用。

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

Best regards. 最好的祝福。

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

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