1、synchronized是java关键字,他是jvm层面; lock是接口(相应的实现比如ReentrantLock);

2、synchronized无法获取到锁的状态, lock可以获取到锁的状态;

3、synchronized是自动锁,如果代码执行完毕或发生异常, 他会自动释放锁的资源, lock手动锁,需要人工进行调用unlock方法进行释放锁的资源, 一般都是放在finally; 如果不释放会发生死锁;

4、synchronized如果线程a获取到锁的资源,发生阻塞,线程b会一直等待, 而lock如果获取不到锁的资源,线程不用等待就结束了;

5、synchronized是可重入、不可中断, 非公平, lock 可重入、 可判断、 可公平(两则皆可);

6、synchronized唤醒线程和等待线程则使用的是Object提供的notify()、wait();方法, 而lock是condition里面提供的signal()、await()方法、 而lock可以获取多个condition可以实现线程循序执行(比如:下面代码1.0);

扩展:

synchronized实现是在jvm中使用monitorenter和monitorexit来实现同步且其中阻塞和唤醒是wait和notify,后者是juc包中的lock层次使用,依赖于AQS来实现加锁和解锁; 

lock一般是通过自旋和cas的方式进行给程序加锁,当有一个线程抢到所的资源,其他则进行等待; 

synchronized在1.6之前每次都要从内核申请额外的锁资源,这样的话都要设计到用户态和内核态的转换,比较浪费资源,而在大多数情况下只有一个线程操作资源,完全不需要重量级锁的。于是就引入了锁升级的过程。

偏向锁:当只有一个线程去抢一个资源,于是就会使用偏向锁,修改偏向锁的状态(记录锁的状态是在我们对象头里面的markwork记录锁的状态),说明这只有a线程来占有;

轻量级锁:于是又来了b、c线程他们就是把偏向锁的标识去除,然后升级到轻量级锁,他是通过cas+自旋的方式来抢锁的资源(这个抢锁的过程还是偏向与前一个申请偏向锁的a线程);

重量级锁:当a线程获取到锁,b、c线程他们一直在抢锁的资源,抢锁的过程他会消耗cpu的资源,如果十个线程过来,那么这些线程一直抢锁的资源,这样对cpu的资源消耗会比较大的,于是就引入了重量级锁,重量级锁是当我们线程自旋次数达到上限他会升级到重量级锁,向内核申请资源,直接让线程阻塞。这样的话会解决多个线程一个抢锁的资源;

1.0


    static final Lock lock = new ReentrantLock();
    static final Condition condition = lock.newCondition();
    static final Condition condition2 = lock.newCondition();
    static final Condition condition3 = lock.newCondition();
    private static int num = 0;

psvm {
    new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 0) {
                        try {
                            condition.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }
                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 1;
                    condition2.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t1").start();

        new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 1) {
                        try {
                            condition2.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }

                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 2;
                    condition3.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t2").start();

        new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (num != 2) {
                        try {
                            condition3.await();
                        } catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                    }
                    System.out.println("【" + Thread.currentThread().getName() + "】");
                    num = 0;
                    condition.signal();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "t3").start();
    }
}

版权声明:本文为qq_42878086原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_42878086/article/details/120056385