synchronized和lock的区别

1. synchronized是jvm层面的,lock是API层面的锁

  1. 使用如下代码验证
public class LockAndSynchronizedDemo {

    public static void main(String[] args) {

        synchronized (new Object()){

        }

        new ReentrantLock();

    }
}
  1. 使用 javap -c LockAndSynchronizedDemo.class 得到字节码指令
public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/Object
       3: dup
       4: invokespecial #1                  // Method java/lang/Object."<init>":()V
       7: dup
       8: astore_1
       9: monitorenter
      10: aload_1
      11: monitorexit
      12: goto          20
      15: astore_2
      16: aload_1
      17: monitorexit
      18: aload_2
      19: athrow
      20: new           #3                  // class java/util/concurrent/locks/ReentrantLock
      23: dup
      24: invokespecial #4                  // Method java/util/concurrent/locks/ReentrantLock."<init>":()V
      27: pop
      28: return

  1. 注意点
    • synchronized 关键字解析出三条关键字节码指令,一条monitorenter,两条monitorexit一个monitorexit是发生异常退出,一个monitorexit是正常退出
    • new ReentrantLock()只是执行了一条new对象的指令,证明了是代码层面的实现,和JVM底层没啥大关系

2. synchronized不需要解锁

  • synchronized不需要向lock一样执行lock.unlock()操作

3. 等待是否可中断

  • synchronized不可以被中断,要等待就得一直等待
  • lock可以使用lock.interrupt()方法进行中断,在等待期间去干别的事

4. synchronized是非公平锁

  • synchronized是非公平锁,不可更改
  • lock可以通过构造函数指定是公平锁还是非公平锁

5. 锁绑定多个条件Condition(精准唤醒)

1. synchronized要么notify(),要么notifyAll(),线程之间的唤醒方式太过单一
2. lock可以精准唤醒,conditionA可以唤醒conditionB,conditionB可以唤醒conditionC

精准唤醒的Condition代码举例

  • A打印五次,C打印十次,B打印15次
//A打印五次,C打印十次,B打印15次
public class PrintDemo {

    public static void main(String[] args) {

        PrintSource printSource = new PrintSource();

        new Thread(() -> {
            printSource.print5();
        },"AAA").start();
        new Thread(() -> {
            printSource.print10();
        },"BBB").start();
        new Thread(() -> {
            printSource.print15();
        },"CCC").start();
    }

}

class PrintSource{

    private Lock lock = new ReentrantLock();
    private Integer number = 1;

    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();

    public void print5(){
         lock.lock();
             try {
                 while(number != 1){
                     condition1.await();
                 }
                 for (int i = 0; i < 5; i++) {
                     System.out.println(Thread.currentThread().getName()+"\t "+i);
                 }
                 number = 2;
                 condition1.signal();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }finally {
                 lock.unlock();
         }
    }

    public void print10(){
        lock.lock();
        try {
            while(number != 2){
                condition2.await();
            }
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName()+"\t "+i);
            }
            number = 3;
            condition2.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void print15(){
        lock.lock();
        try {
            while(number != 3){
                condition3.await();
            }
            for (int i = 0; i < 15; i++) {
                System.out.println(Thread.currentThread().getName()+"\t "+i);
            }
            number = 1;
            condition3.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页