资讯专栏INFORMATION COLUMN

CAS也是锁

Flands / 2807人阅读

摘要:先比较,发现与预期一致,说明没有其他线程改动过,于是就交换如果不一致说明改动过,就再来一次,如此往复。所谓无锁是在层面上没有锁,但其实在操作系统的指令层面是加了锁的。这个锁比上的锁性能好很多。

CAS(CompareAndSwap)顾名思义比较再交换。先比较,发现与预期一致,说明没有其他线程改动过,于是就交换;如果不一致说明改动过,就再来一次,如此往复。

int prev, next;
do {
    prev = get();
    next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;

这是一种自旋的方式保证线程安全,可是compareAndSet这个比较再交换是原子的吗?先比较发现与预期一致了,准备交换的时候另一个线程来改了怎么办?
点进去看源码:

public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

这个unsafe的方法都是native方法,

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

只能打开openJDK看源码了

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

核心方法是cmpxchg方法

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

原来LOCK_IF_MP这里加了锁,才保证了原子性。所谓“无锁”是在Java层面上没有锁,但其实在操作系统的CPU指令层面是加了锁的。这个锁比java上的锁性能好很多。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75080.html

相关文章

  • Java 中关于锁的一些理解

    摘要:每一个被锁住的对象都会和一个关联对象头的中的指向的起始地址,同时中有一个字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用。 jdk 6 对锁进行了优化,让他看起来不再那么笨重,synchronized有三种形式:偏向锁,轻量级锁,重量级锁. 介绍三种锁之前,引入几个接下来会出现的概念 mark work: 对象头,对象头中存储了一些对象的信息,这个是锁的根本,任何锁都需要依赖m...

    Yumenokanata 评论0 收藏0
  • 深入理解Java内存模型(五)——锁

    摘要:前情提要深入理解内存模型四锁的释放获取建立的关系锁是并发编程中最重要的同步机制。锁内存语义的实现本文将借助的源代码,来分析锁内存语义的具体实现机制。请看下篇深入理解内存模型六 前情提要 深入理解Java内存模型(四)—— volatile 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还可以让释放锁的线程向...

    caige 评论0 收藏0
  • 锁和分布式锁

    摘要:锁的部分细节不同场景锁的表现不同独占共享读写分布式锁的简单实现分布式锁实现的三个核心要素加锁最简单的方法是使用命令。尝试获取分布式锁客户端锁线程超期时间是否获取成功释放分布式锁客户端锁请求标识是否释放成功 锁的由来: 多线程环境中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,这就需要某种机制来保证只有满足某个条件(获取锁成功)的线程才能访问资源...

    codeGoogle 评论0 收藏0
  • 且听我一个故事讲透一个锁原理之synchronized

    摘要:第三天,太监传话钦天监求见一日无事。第四天,钦天监一日无事。然后所有的竞争线程放弃自旋,逐个插入到对象里的一个队列尾部,进入阻塞状态。 微信公众号:IT一刻钟大型现实非严肃主义现场一刻钟与你分享优质技术架构与见闻,做一个有剧情的程序员关注可第一时间了解更多精彩内容,定期有福利相送哟。 showImg(https://segmentfault.com/img/bVbrgsJ?w=900...

    gougoujiang 评论0 收藏0

发表评论

0条评论

Flands

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<