synchronized和lock比较

1,620 阅读3分钟

 两种锁的比较

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