首先在一个对象中,对于所有的非静态方法使用synchronized关键字修饰的方法,它们是同一个锁是this,这意味着某一个synchronized 关键字 修饰的非静态方法,其它的非静态方法都要等待直至该方法执行完成。然后,对于静态方法synchronized 关键字 修饰的方法是非互斥的,使用的锁是类名.class。它不需要等待其它方法的行结果。

结论是使用synchronized修饰的静态方法和非静态方法它们不是一把锁。非静态方法的锁是this,静态方法的锁是类.class。多个静态方法也不是互斥

先看非静态方法的例子:

public class SyncExample  {

    public synchronized void func1()  {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("调用第1个synchronized修饰的方法");
    }
    public synchronized void func2(){
        System.out.println("调用第2个synchronized修饰的方法");
    }

    public static void main(String[] args) throws InterruptedException {
        SyncExample sync = new SyncExample();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                sync.func1();
            }
        });
        System.out.println("开启线程1");
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                sync.func2();
            }
        });
        System.out.println("开启线程2");
        t2.start();

    }
}

测试一下

输出

开启线程1
开启线程2
调用第1个synchronized修饰的方法
调用第2个synchronized修饰的方法

 我们看到第二个方法func2需要等待第一个方法func1执行完成后再执行。因为它们使用的是同一把锁。

再看一个静态方法和非静态方法的综合例子:

public class SyncExample2  {

    public synchronized void func1()  {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("调用第1个synchronized修饰的方法");
    }
    public synchronized void func2(){
        System.out.println("调用第2个synchronized修饰的方法");
    }

    public synchronized static void func3(){
        System.out.println("调用第3个synchronized修饰的静态方法");
    }

    public static void main(String[] args) throws InterruptedException {
        SyncExample2 sync2 = new SyncExample2();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                sync2.func1();
            }
        });
        System.out.println("开启线程1");
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                sync2.func2();
            }
        });
        System.out.println("开启线程2");
        t2.start();

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                sync2.func3();
            }
        });
        System.out.println("开启线程3");
        t3.start();

    }
}

测试一下

输出:
开启线程1
开启线程2
开启线程3
调用第3个synchronized修饰的静态方法
调用第1个synchronized修饰的方法
调用第2个synchronized修饰的方法

 从结果中看出,方法1和方法2是互斥的,和之前一样,而对于方法3,synchronized 修饰的是静态方法,和他们的锁不一样,就不存在互斥的情况,所以结果中会先输出方法3 的结果。