Java基础-锁

Java具有很多的锁机制,为保证并发和性能兼顾,需要合理选择
其实锁的实现是通过对象头中的Mark Word指定线程的地址或者名称,线程栈帧中开辟一个空间Lock Record,用于存储锁对象目前的 Mark Word 的拷贝,然后拷贝对象头中的 Mark Word 复制到锁记录中。其他线程要获得锁,就修改Mark Word指定线程的地址或者名称。这里用CAS的重试来实现。

1、公平锁/非公平锁。

(1)公平锁:使用阻塞队列,如果多个线程竞争锁,那就先入先出呗,这样唤醒线程代价比较高,因为其他线程都堵塞
(2)非公平锁:非公平就是有特权咯。线程上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程。缺点是处于等待队列中的线程可能会饿死,或者等很久才会获得锁。

2、可重入锁

简单啦,线程可以递归、嵌套获取锁(A占锁,没结束又要占锁,直接持有,不必放开再持有)
如果没有可重入锁,递归获取锁容易出死锁。

3、独享锁/共享锁

(1)共享锁:多个线程可以同时持有。如ReadWriteLock,其读锁是共享锁,其写锁是独享锁。读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。
(2)独享锁:只有一个线程同时持有。如 ReentrantLock、synchronized

4、乐观锁/悲观锁

(1)乐观锁:CAS实现(获取期望值,对比期望值,更改为新值)
通常读比写要多。因而我们认为拿到的共享数据是未经过其他程序改变的,所以不加锁。但是总有意外,如果数据改变了就会有脏数据。所以我们:先获取要修改变量当前值A; 然后拿出新值B;真正修改前需要比对当前线程中的A值与内存中的A值是否相等,如果相等,则修改为B。
但仍会出现ABA,因为可以修改100为50,再修改50为100,这样多线程仍会出现脏数据,这时候需要用version变量自加来避免版本不同的50或100。
(2)悲观锁:认为脏数据总是出现,所以拿数据之前就加上锁,一个线程持有锁,另外一个线程不可以持有;

多读:悲观锁
多写:乐观锁

5、分段锁

就是把一个数据接口分成几段就行存储,每一段有一个锁,,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。
多种锁的讲述
synchronized 关键字设置了四种状态,它们分别是:无锁、偏向锁、轻量级锁和重量级锁,
Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的,监视器锁本质又是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么 Synchronized 效率低的原因。因此,这种依赖于操作系统 Mutex Lock 所实现的锁我们称之为重量级锁。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值