java 常用的锁
Synchronized, 它就是一个: 非公平, 悲观, 独享, 互斥, 可重入的重量级锁
ReentrantLock, 它是一个: 默认非公平但可实现公平的, 悲观, 独享, 互斥, 可重入, 重量级锁.
ReentrantReadWriteLocK, 它是一个, 默认非公平但可实现公平的, 悲观, 写独享, 读共享, 读写, 可重入, 重量级锁.
5.ReentrantLock 和 Synchronized 区别
ReentrantLock: 代码来实现的, 要保证锁释放, 必须将 unlock() 放到 finally{} 中.
Synchronized: 是 JVM 层面上的. 代码执行异常的时候会自动释放锁.
在资源竞争不是很激烈的情况下, Synchronized 的性能要优于 ReetrantLock,
但是在资源竞争很激烈的情况下, Synchronized 的性能会下降几十倍, 但是 ReetrantLock 的性能能维持常态;
所以, 我们写同步的时候, 优先考虑 synchronized, 如果有特殊需要, 再进一步优化.
ReentrantLock 和 Atomic 如果用的不好, 不仅不能提高性能, 还可能带来灾难.
6.ReentrantLock 获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回, 如果别的线程持有锁, 当前线程则一直处于休眠状态, 直到获取锁
b) tryLock(), 如果获取了锁立即返回 true, 如果别的线程正持有锁, 立即返回 false;
c)tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回 true, 如果别的线程正持有锁, 会等待参数给定的时间, 在等待的过程中, 如果获取了锁定, 就返回 true, 如果等待超时, 返回 false;
d) lockInterruptibly: 如果获取了锁定立即返回, 如果没有获取锁定, 当前线程处于休眠状态, 直到或者锁定, 或者当前线程被别的线程中断
7. 锁的分类
悲观锁 / 乐观锁
悲观锁: 拿数据就加锁, 适合写操作多大情况. 例: synchronized
乐观锁: 拿数据不加锁, 改数据判断下在此期间数据有没有被更新, 可以使用版本号机制, CAS(Compare and Swap 比较并交换) 操作.
独享锁 / 共享锁
独享锁: 是指该锁一次只能被一个线程所持有. 例: RenntrantLock,Synchronized
共享锁: 是指该锁可被多个线程所持有. 例: ReentrantReadWriteLock
ReadWriteLock: 读是共享锁, 写是独享锁
可重入锁: 可重入锁又名递归锁, 是指在同一个线程在外层方法获取锁的时候, 在进入内层方法会自动获取锁
例: ReetrantLock,Synchronized
- synchronized void setA() throws Exception{
- Thread.sleep(1000);
- setB();
- }
- synchronized void setB() throws Exception{
- Thread.sleep(1000);
- }
公平锁 / 非公平锁
公平锁: 是指多个线程按照申请锁的顺序来获取锁. 例: ReetrantLock
非公平锁: 是指多个线程获取锁的顺序并不是按照申请锁的顺序. 有可能, 会造成优先级反转或者饥饿现象. 例: Synchronized
分段锁: ConcurrentHashMap
自旋锁 / 偏向锁 / 轻量级锁 / 重量级锁
自旋锁: 尝试获取锁的线程不会立即阻塞, 而是循环尝试获取锁. 减少线程上下文切换的消耗. 缺点是循环会消耗 CPU.
偏向锁: 一段代码一直被一个线程访问. 那么该线程就会自动获取锁. 降低取锁代价.
轻量级锁: 偏向锁被另一个线程访问, 会自动升级为轻量级锁. 其他线程也会通过自旋形式获取锁, 不会阻塞, 提高性能.
重量级锁: 轻量级锁, 另一个线程虽然自旋, 一直持续自旋没有获取锁, 该锁膨胀为重量级锁. 重量级锁会让他申请线程进入阻塞, 性能降低
来源: http://www.bubuko.com/infodetail-3685893.html