首先在一个对象中,对于所有的非静态方法使用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修饰的方法
开启线程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修饰的方法
开启线程2
开启线程3
调用第3个synchronized修饰的静态方法
调用第1个synchronized修饰的方法
调用第2个synchronized修饰的方法
从结果中看出,方法1和方法2是互斥的,和之前一样,而对于方法3,synchronized 修饰的是静态方法,和他们的锁不一样,就不存在互斥的情况,所以结果中会先输出方法3 的结果。