首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >再次设置AtomicBoolean

再次设置AtomicBoolean
EN

Stack Overflow用户
提问于 2018-11-22 16:26:07
回答 2查看 204关注 0票数 4

我正在使用一个AtomicBoolean来执行线程之间的volatile可见性。一个线程正在更新该值,另一个线程只在读取它。

假设当前值是true。现在假设写线程再次将其值设置为true

代码语言:javascript
复制
final AtomicBoolean b = new AtomicBoolean(); // shared between threads

b.set(true);
// ... some time later
b.set(true);

在这个“虚拟”set(true)之后,当读取线程调用get()时会有性能损失吗?读取线程必须重新读取并缓存值吗?

如果是这样的话,写线程可能会这样做:

代码语言:javascript
复制
b.compareAndSet(false, true);

这样,读取线程只需对实际更改无效。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-22 17:14:57

compareAndSet()

代码语言:javascript
复制
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()已经是本地的:

代码语言:javascript
复制
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

在JVM执行开始时的某个地方,Atomic::cmpxchg已生成,如

代码语言:javascript
复制
  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代码(它也有更长的遗留代码路径,因此我在这里不复制该代码):

代码语言:javascript
复制
 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文档所言:

此指令可与锁前缀一起使用,以允许以原子方式执行指令。为了简化到处理器总线的接口,目标操作数接收一个写周期,而不考虑比较的结果。如果比较失败,则返回目标操作数;否则,源操作数将写入目标。(处理器不会产生锁定的读,同时也会产生锁定的写。)

因此,在多处理器x86机器上,NOP也会进行写操作,从而影响缓存行.(重点是我补充的)

票数 3
EN

Stack Overflow用户

发布于 2018-11-22 16:33:24

写和CAS都“触摸”了触发缓存行脏的高速缓存行。

然而,成本相对较低,在30-50 ns之间。

由于代码还没有运行10,000次,所以代码的成本可能要高得多。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53434995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档