1. 锁类 (Class对象)

灵活度低,比如一个类他两个方法,都用的synchronized锁,并发情况下两个方法都要互相等待
举个例子:a方法和b方法实际上都是不相干的,比如a方法操作a表数据,b方法操作b表数据,根本不会存在冲突,但是并发时候仍然会导致两个方法进行互相等待

public class Demo {

    public static synchronized void a() {
        System.out.println(Thread.currentThread().getName() + " 进入方法 A");
        try { Thread.sleep(3000); } catch (Exception ignored) {}
        System.out.println(Thread.currentThread().getName() + " 离开方法 A");
    }

    public static synchronized void b() {
        System.out.println(Thread.currentThread().getName() + " 进入方法 B");
        try { Thread.sleep(3000); } catch (Exception ignored) {}
        System.out.println(Thread.currentThread().getName() + " 离开方法 B");
    }

    public static void main(String[] args) {
        new Thread(Demo::a, "线程1").start();
        new Thread(Demo::b, "线程2").start();
    }
}
  1. 锁实例

就不会这样,如果改成非静态:

public synchronized void a() { }
public synchronized void b() { }

但实例不同:

Demo d1 = new Demo();
Demo d2 = new Demo();

new Thread(d1::a).start();
new Thread(d2::b).start();

→ 互不影响(因为锁的是不同的 this)

  1. 锁方法

灵活度最高,可以自己控制拿哪一把锁,甚至可以在方法A中里面后在加一把synchronized拿lockB的锁,一个方法的话如果用了多把锁的话,要注意有没有死锁风险

public class MyService {

    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void methodA() {
        synchronized (lockA) {  // 锁 A
            System.out.println("A 开始");
            try { Thread.sleep(2000); } catch (Exception e) {}
            System.out.println("A 结束");
        }
    }

    public void methodB() {
        synchronized (lockB) {  // 锁 B
            System.out.println("B 开始");
            try { Thread.sleep(2000); } catch (Exception e) {}
            System.out.println("B 结束");
        }
    }
    public static void main(String[] args) {
        MyService s = new MyService();
        new Thread(() -> s.methodA()).start();
        new Thread(() -> s.methodB()).start();
    }
}