【面试】Java多线程中各种锁

Java多线程中各种锁

名词

CAS自旋锁

1、什么是CAS?
执行循环,不断比较线程副本的值和多个线程共享的值是否相同,相同不交换,不相同交换。
CAS (compareAndSwap),中文叫比较交换,是一种无锁原子算法,映射到操做系统就是一条CPU的原子指令,其做用是让CPU先进行比较两个值是否相等,而后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在intel的CPU中,使用的是cmpxchg指令,就是说CAS是靠硬件实现的,从而在硬件层面提高效率。
执行过程是这样:它包含 3 个参数 CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当 V值等于E值时,才会将V的值设为N,若是V值和E值不一样,则说明已经有其余线程完成更新,则当前线程则什么都不作,最后CAS 返回当前V的真实值。
当多个线程同时使用CAS 操做一个变量时,最多只有一个会胜出,并成功更新,其他均会失败。失败的线程不会挂起,仅是被告知失败,而且容许再次尝试(自旋),固然也容许实现的线程放弃操做。基于这样的原理,CAS 操做即便没有锁,也能够避免其余线程对当前线程的干扰。
与锁相比,使用CAS会使程序看起来更加复杂一些,可是使用无锁的方式彻底没有锁竞争带来的线程间频繁调度的开销和阻塞,它对死锁问题天生免疫,所以他要比基于锁的方式拥有更优越的性能。
简单的说,CAS 须要你额外给出一个指望值,也就是你认为这个变量如今应该是什么样子的。若是变量不是你想象的那样,说明它已经被别人修改过了。你就须要从新读取,再次尝试修改就行了。

2、CAS底层原理
这样归功于硬件指令集的发展,实际上,咱们可使用同步将这两个操做变成原子的,可是这么作就没有意义了。因此咱们只能靠硬件来完成,硬件保证一个从语义上看起来须要屡次操做的行为只经过一条处理器指令就能完成。这类指令称为原子指令,经常使用的有:
(1)测试并设置(Tetst-and-Set)
(2)获取并增长(Fetch-and-Increment)
(3)交换(Swap)
(4)比较并交 换(Compare-and-Swap)
(5)加载连接/条件存储(Load-Linked/Store-Conditional)

3、CPU 实现原子指令的两种方式
(1)经过总线锁定来保证原子性。
总线锁定其实就是处理器使用了总线锁,所谓总线锁就是使用处理器提供的一个 LOCK# 信号,当一个处理器在总线上输出此信号时,其余处理器的请求将被阻塞住,那么该处理器能够独占共享内存。可是该方法成本太大。所以有了下面的方式。
(2)过缓存锁定来保证原子性。
所谓 缓存锁定 是指内存区域若是被缓存在处理器的缓存行中,而且在Lock 操做期间被锁定,那么当他执行锁操做写回到内存时,处理器不在总线上声言 LOCK# 信号,而时修改内部的内存地址,并容许他的缓存一致性机制来保证操做的原子性,由于缓存一致性机制会阻止同时修改两个以上处理器缓存的内存区域数据(这里和 volatile 的可见性原理相同),当其余处理器回写已被锁定的缓存行的数据时,会使缓存行无效。
注意:有两种状况下处理器不会使用缓存锁定:
当操做的数据不能被缓存在处理器内部,或操做的数据跨多个缓存行时,则处理器会调用总线锁定。
有些处理器不支持缓存锁定,对于 Intel 486 和 Pentium 处理器,就是锁定的内存区域在处理器的缓存行也会调用总线锁定

Java实现

Synchronized 或 ReentrantLock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值