Java线程安全和锁

目录

 

1、CAS算法

2、Synchronized实现原理

3、锁优化

(1) 自旋锁

(2) 适应性自旋锁

(3) 锁消除

(4) 锁粗化

(5) 偏向锁

(6) 轻量级锁

(7) 乐观锁

(8) 悲观锁

4、i++是否线程安全


1、CAS算法

        Cas(Compare and Swap),传入有三个值V、a、b,V是内存值,a是预期值,b是更新值,当事务提交时,从内存中获取值V,并与传入的预期值a比较,若两者相等,则将a值更新为b;否则不做任何操作或重新进行操作。CAS算法实际是一种乐观锁,自旋锁是基于此实现;底层利用CPU指令保证原子性;只对单一指针/值起作用。

2、Synchronized实现原理

        对象头中的Mark Word部分,会记录当前持有对象的线程ID以及是什么锁(轻量级锁、偏向锁、重量级锁等)。轻量级锁会使用CAS尝试改变持有锁的线程ID和锁的标志位,若成功则获取锁;偏向锁连CAS算法都不使用,进一步减小开销。偏向锁会先膨胀为轻量级锁,轻量级锁又会膨胀为重量级锁。

3、锁优化

(1) 自旋锁

        用一个死循环来尝试获取锁,若失败则继续获取,直到获取到所需资源的锁。

(2) 适应性自旋锁

        根据前一次自旋状态,修改自旋次数等。

(3) 锁消除

        对于不可以逃逸的对象,消除锁,例如局部变量中的vector、StringBuffer等线程安全对象。

(4) 锁粗化

        将多个连续的加锁、解锁合并成一个锁。

(5) 偏向锁

        线程执行完之后不会释放锁,直到下一个线程来时判断是否为上一次使用的线程,若是则可以直接使用;适用于在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,可以减少加锁解锁的CAS操作;当出现多线程竞争时会先变为轻量级锁。

(6) 轻量级锁

        在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗;出现多线程竞争时会膨胀为重量级锁。

(7) 乐观锁

        一般的实现乐观锁的方式就是记录数据版本,实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳。即在事务提交时检查,若版本号或时间戳与之前获取的不一样,则说明在此之前已经有其他线程对其修改,本线程需要重新执行事务。

(8) 悲观锁

        一般使用 select ...for update 对所选择的数据进行加锁(悲观锁)处理。

4、i++是否线程安全

        不是线程安全的,i++ 在 cpu 中实际分为三步操作,

temp = i;
temp2 = temp + 1;
i = temp2;

        这三步并没有加锁,因此不是线程安全的,不同线程执行i++可能会导致覆盖更新的问题。可以AtomicInteger 类来保证线程安全,其底层使用的是cas算法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值