Synchronized:
1、synchronized修饰后,操作顺序为:拿到锁->进行操作->释放锁,无法手动干预
Lock:
1、lock() 获得锁
2、lockInterruptibly() 中断锁的过程
3、tryLock() 尝试获得锁
4、tryLock(long time, TimeUnit unit) 尝试获得锁,并添加超时时间
5、unlock() 释放锁
可重入锁:
- synchronized 和 ReentrantLock 都属于可重入锁
- 程序内部包含一个计数器,获得一次锁,计数器就会+1,释放一次锁,计数器就会-1。当锁完全释放完毕,计数器为0。
public class LockDemo {
private Lock lock = new ReentrantLock();
private int count = 0;
public void increase(){
lock.lock();
try {
count++;
} finally{
//因为获得的锁一定要释放,所以释放锁的代码,一定要在 finally 中执行。
lock.unlock();
}
}
public synchronized void add(){
count++;
}
public synchronized void add2(){
add();//可重入锁
}
}
公平锁和非公平锁:
- 如果在时间上,先对锁进行获取的请求,一定先得到满足,那么这么锁就是公平的,反之,则是非公平的。
- 非公平锁的性能要高于公平锁。
A目前拿到了锁。
B去获取锁,失败,则B线程处于挂起状态。
此时C线程请求过来,
若是公平锁,则应在B处理完毕后,再去获得锁。
若是非公平锁,则会直接获取锁,因为B线程从挂起状态,变更为重新获取锁状态,需要一定的时间,则C线程有可能在这段时间内已经获得了锁并工作完毕,充分利用了时间。 - ReentrantLock 默认是非公平锁,在初始化ReentrantLock时,可设置ReentrantLock是否为公平锁。
public class ReentrantLock implements Lock, java.io.Serializable {
private final Sync sync;
/**
*无参构造函数-默认非公平锁
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
*有参数构造函数
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
}
总结:
根据以上总结的 ReentrantLock 和 Synchronized 特点来判断使用哪种锁。