欢迎关注微信公众号:互联网全栈架构
在Java并发编程中,我们经常需要给代码块或者方法加锁,而常用的加锁方法有Lock和synchronized,那么,这两者有什么区别呢?搞清楚这两者之间的异同,除了对日常的编程工作有帮助外,它也常常出现在面试题目当中。我们先逐条分析它们的主要区别,在文章最后再用一个表格进行总结,以便对于这个知识点能够一目了然。
一、首先,Lock是Java的一个接口,是JDK提供的API,而synchronized是Java的关键字,在几十个Java关键字中,它赫然在列。
二、线程获取synchronized锁,在执行完成后会自动释放锁,而Lock需要手动进行释放。为了更好地理解两者之间的差异,我们用一个简单的例子来进行说明,定义两个简单的并发类用于计数,分别用synchronized关键字和Lock接口加锁:
package com.sample.multithread.base;
// 使用synchronized关键字加锁
public class SynchronizedDemo {
private long count = 0;
// 计数器加1
public synchronized void add(){
count++;
}
// 获取计数器的值
public synchronized long getCount(){
return count;
}
}
package com.sample.multithread.base;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// 使用接口Lock加锁
public class LockDemo {
private long count = 0;
// Lock的接口实现类,通常使用ReentrantLock
private Lock lock = new ReentrantLock();
// 计数器加1
public void add(){
lock.lock();
try{
count++;
}finally {
lock.unlock();
}
}
// 获取计数器的值
public long getCount(){
lock.lock();
try{
return count;
}finally {
lock.unlock();
}
}
}
从上面的代码可以看出,因为synchronized是Java的关键字,所以它的代码要简洁得多,而Lock接口需要手动调用方法进行加锁,在使用完成后,还需要调用unlock方法手动解锁。
另外,对于synchronized关键字,在代码正常执行完成以后,线程就会自动释放锁,如果代码发生异常,或者调用对象的wait方法时,线程也会自动释放锁。
三、Lock可以通过tryLock方法判断锁的状态,而synchronized没有办法来查询锁的状态。另外,tryLock还可以指定超时时间,如果在指定的时间范围内没有获得锁,则返回false。
四、synchronized可以锁住方法和代码块,而Lock只能锁住代码块。
五、synchronized是非公平锁,且不支持公平锁,而Lock默认是非公平锁,也支持公平锁。
六、从应用场景来说,如果是简单的并发场景,使用synchronized比较适合,但对于资源竞争比较激烈,或者锁控制粒度更细的场景中,使用Lock会更合适。
下面用一个表格来总结一下两者的主区别:
都看到这里了,请帮忙一键三连啊,也就是点击文末的在看、点赞、分享,这样会让我的文章让更多人看到,也会大大地激励我进行更多的输出,谢谢!
鸣谢:
https://www.geeksforgeeks.org/lock-framework-vs-thread-synchronization-in-java/
推荐阅读: