- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用 AtomicBoolean
来强制执行线程之间的 volatile
可见性。一个线程正在更新值,另一个线程只读取它。
假设当前值为 true
。现在假设一个写线程再次将其值设置为true
:
final AtomicBoolean b = new AtomicBoolean(); // shared between threads
b.set(true);
// ... some time later
b.set(true);
在这个“虚拟”set(true)
之后,当读取线程 调用get()
时是否有性能损失? 读取线程是否必须重新读取并缓存该值?
如果是这种情况,写入线程 可以完成:
b.compareAndSet(false, true);
这样,读取线程只需为真正的变化而失效。
最佳答案
public final boolean compareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
int u = update ? 1 : 0;
return unsafe.compareAndSwapInt(this, valueOffset, e, u);
}
compareAndSwapInt()
已经是原生的了:
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
UnsafeWrapper("Unsafe_CompareAndSwapInt");
oop p = JNIHandles::resolve(obj);
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
其中 Atomic::cmpxchg
是 JVM 执行开始时某处的 generated 为
address generate_atomic_cmpxchg() {
StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg");
address start = __ pc();
__ movl(rax, c_rarg2);
if ( os::is_MP() ) __ lock();
__ cmpxchgl(c_rarg0, Address(c_rarg1, 0));
__ ret(0);
return start;
}
cmpxchgl()
生成 x86 代码(它也有更长的遗留代码路径,所以我不在这里复制那个):
InstructionMark im(this);
prefix(adr, reg);
emit_byte(0x0F);
emit_byte(0xB1);
emit_operand(reg, adr);
0F
B1
实际上是一个 CMPXCHG
操作。如果你检查上面的代码,if ( os::is_MP() ) __ lock();
在多处理器机器上发出一个 LOCK
前缀(让我跳过引用 lock()
,它发出一个 F0
字节),所以几乎无处不在。
正如 CMPXCHG
文档所说:
This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically. To simplify the interface to the processor’s bus, the destination operand receives a write cycle without regard to the result of the comparison. The destination operand is written back if the comparison fails; otherwise, the source operand is written into the destination. (The processor never produces a locked read without also producing a locked write.)
因此,在多处理器 x86 机器上,NOP-CAS 也会进行写入操作,从而影响缓存行。 (重点是我加的)
关于java - 再次设置 AtomicBoolean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53434995/
我想知道调用之间是否有任何区别(或可能的副作用): AtomicBoolean.set(true) 和 AtomicBoolean.compareAndset(false, true) AtomicB
我正在实现一个标准的生产者-消费者程序,以便生产者在生产 200 个产品后停止。为了表明这一点,生产者将 -1 放入 BlockingQueue 变量中,否则该变量始终包含正整数。我的消费者实现如下:
AtomicBoolean 使用 native 代码进行同步。它如何转化为 java 锁? 有什么区别: AtomicBoolean a = new AtomicBoolean(); synchron
我了解 AtomicInteger 的有效用例,但我对 AtomicBoolean 如何保证两个操作的原子性感到困惑 i. '改变 boolean 值'和ii。在以下经常引用的 AtomicBoole
我经常使用以下模式来创建可取消的线程: public class CounterLoop implements Runnable { private volatile AtomicBoolea
我正在使用 AtomicBoolean 来强制执行线程之间的 volatile 可见性。一个线程正在更新值,另一个线程只读取它。 假设当前值为 true。现在假设一个写线程再次将其值设置为true:
我有一个系统,有很多写入器和一个读取器,每个读取器都在一个单独的线程中运行。当工作可用时,作者会通知读者,而读者会阻塞,直到收到通知。 鉴于作者的数量,我想使用无锁实现来通知读者。每次读者醒来时,它都
在我正在开发的应用程序中,我发现了以下代码片段: public class MyClass { private AtomicBoolean atomicBoolean = new Atomic
我不喜欢用 synchronized(this) 锁定我的代码,所以我正在尝试使用 AtomicBooleans。在代码片段中,XMPPConnectionIF.connect() 与远程服务器建立套
这个问题已经有答案了: When is it preferable to use volatile boolean in Java rather than AtomicBoolean? [duplic
我需要确保每个实例生命周期仅执行一次特定的启动和停止代码,并且该实例无法“重新启动”。以下代码足以满足多个线程可能对实例进行操作的场景吗? public final class MyRunnable
我有一个简单的类,我想使用 AtomicBoolean 测试它的线程安全性。如果测试的线程超过 2 个,则它不起作用。它在某些线程的 doSome 方法中抛出 NullPointerExcetion:
阅读此代码AsyncSubscriber.java :编码器使用 AtomicBoolean 创建 Happens Before 关系,我想知道: 1_是否相当于使用synchronized bloc
MyRunnable 有一个原子 boolean 值,需要通过一种方法将其设置为 true, 另一种在多线程环境中设置为 false 的方法 private final class MyRunn
我有下一个任务 public class QuittableTask implements Runnable { final int id; public QuittableTask(int
我正在为 AtomicInteger 和 AtomicBoolean 编写单元测试。它们将用作引用测试,用于测试 objective-c 中这些类的仿真,用于翻译项目。 我认为 AtomicInteg
这是我编写的一些代码,用于以通用方式处理一个事件处理程序,该事件处理程序对于任何 JavaFX 事件都应该只触发一次: public final class OneShotEvent impl
如何确保 initialize() 方法只被调用一次?下面是我想重构为使用 AtomicBoolean 的线程不安全版本。 我只想要 initialize() 只被调用一次 if (!initiali
我正在寻找一种暂停线程的方法。 我开始使用一个 boolean 标志(称为“暂停”),并用一个 while 循环(暂停)包装一个检查。 在 while 循环中有一个 Thread.wait() 来阻止
我将 lambda 表达式作为参数传递给方法,并且我想修改在 lambda 表达式之外定义的变量。 我已经尝试了几件事。目前,我有一个 AtomicBoolean调用success .在 lambda
我是一名优秀的程序员,十分优秀!