Java中的锁机制
Lock不是Java语言内置的, synchronized是Java语言中的关键字, Lock是一个接口,通过这个接口可以实现同步访问。
Lock允许更灵活的结构, 并可以支持多个相关类的条件对象。优势在于: 使锁更公平, 使线程在等待锁的时候可以响应中断; 可以让线程尝试获取锁, 并在无法获取锁的时候立即返回或等待一段时间。
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
重入锁(ReentrantLock)是一种递归无阻塞的同步机制,指的是当同一线程的外层函数获得锁之后, 内层的递归调用函数仍然可以获取得到该锁的代码。
一个实例:
class MyClass {
public synchronized void method1() {
method2();
}
public synchronized void method2() {
}
}
上述代码中的两个方法method1 和 method2 都用synchronized 关键字修饰, 假如某一个时刻, 线程A执行到了method1, 此时线程A获取了该对象的锁, 但是由于method2也是synchronized方法, 假如synchronized不具备可重入性, 那么线程A需要重新申请一个锁, 但是这会造成一个问题是线程A已经有了该对象的锁,而又在申请该对象的锁,产生了一个自环, 就会造成永远等待。
ReentrantLock和synchronized
都可以得到可重入锁
读写锁: 针对读写操作的不同特点设计的锁结构
公平锁: 按照请求锁的顺序来获取锁。比如同样是多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程会获得该锁
可中断锁:可以中断的锁 syncrhonized不是可中断锁, Lock是可中断锁
如果线程A正在执行
乐观锁与悲观锁
悲观锁: 每次去拿数据都会上锁, 传统的关系型数据库都会用到这种机制,比如行级锁, 写锁
乐观锁: 每次读数据认为别人不会修改,所以不会上锁, 但是在更新的时候会判断在此期间有没有人更新这个数据,适用于读操作多的情况