两种锁的比较
1.1 synchronized和lock的区别
- Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
- synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
- Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
- 性能上来说,在资源竞争不激烈的情形下,Lock性能稍微比synchronized差点(编译程序通常会尽可能的进行优化synchronized)。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。
1.2 性能比较
下面对synchronized与Lock进行性能测试,分别开启10个线程,每个线程计数到1000000,统计两种锁同步所花费的时间。网上也能找到这样的例子。
public class TestAtomicIntegerLock {
private static int synValue;
public static void main(String[] args) {
int threadNum = 10;
int maxValue = 1000000;
testSync(threadNum, maxValue);
testLocck(threadNum, maxValue);
}
//test synchronized
public static void testSync(int threadNum, int maxValue) {
Thread[] t = new Thread[threadNum];
Long begin = System.nanoTime();//纳秒 1毫秒=1纳秒*1000*1000
Lock locks = new ReentrantLock();
for (int i = 0; i < threadNum; i++) {
synValue = 0;
t[i] = new Thread(() -> {
for (int j = 0; j < maxValue; j++) {
locks.lock();
try {
synValue++;
} finally {
locks.unlock();
}
}
});
}
for (int i = 0; i < threadNum; i++) {
t[i].start();
}
//main线程等待前面开启的所有线程结束
for (int i = 0; i < threadNum; i++) {
try {
t[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("使用lock计算结果:" + synValue);
System.out.println("使用lock所花费的时间为纳秒:" + (System.nanoTime() - begin));
System.out.println("使用lock所花费的时间为毫秒:" + (System.nanoTime() - begin)/(1000*1000));
}
// test Lock
public static void testLocck(int threadNum, int maxValue) {
int[] lock = new int[0];
Thread[] t = new Thread[threadNum];
Long begin = System.nanoTime();
for (int i = 0; i < threadNum; i++) {
synValue = 0;
t[i] = new Thread(() -> {
for (int j = 0; j < maxValue; j++) {
synchronized(lock) {
++synValue;
}
}
});
}
for (int i = 0; i < threadNum; i++) {
t[i].start();
}
//main线程等待前面开启的所有线程结束
for (int i = 0; i < threadNum; i++) {
try {
t[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("使用synchronized计算结果:" + synValue);
System.out.println("使用synchronized所花费的时间为纳秒:" + (System.nanoTime() - begin));
System.out.println("使用synchronized所花费的时间为毫秒:" + (System.nanoTime() - begin)/(1000*1000));
}
测试结果的差异还是比较明显的,Lock的性能明显高于synchronized。本次测试基于JDK1.8。
使用lock计算结果:10000000
使用lock所花费的时间为纳秒:325498123
使用lock所花费的时间为毫秒:325
使用synchronized计算结果:10000000
使用synchronized所花费的时间为纳秒:369050105
使用synchronized所花费的时间为毫秒:369
参考来源:https://juejin.cn/post/6844903542440869896