锁定代码块等价于锁定对象
首选看一下锁定代码块的语法?
synchronized (对象)
{
// 代码块
}
上面的语法中的"对象",指的是实例对象,可以是this
,Class.clss
或者其他共享对象
.所以代码块锁定的等价于对象锁定.我们甚至还可以假设一下.把上面代码的"对象"做成变量:
public void func1(Object lock) {
// 这个方法没有锁定,锁定的是里面的代码块
synchronized (lock) {
System.out.println("方法开始");
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("方法结束");
}
}
那如果我们锁住的不是lock
对象,而是func1
里面的代码,那无论传入的lock
对象是什么,这段代码都不能并发执行了.这显然是不可能的.我们看看输出也再次证明了这个结论:
方法开始
方法开始
方法结束
方法结束
锁定非静态方法等价于锁定对象
先抛出原因:
对象的非静态 synchronized 方法被调用的时候,会先将对象锁定,类似自动调用synchronized(this).
验证:
假如我们一个进程先调用对象的非静态 synchronized 方法,然后另一个进程调用 synchronized(this).
如果第一个进程没有为对象加锁,第二个进程就能调用成功,然后两者是并行的,结论不成立
反之,第二个进程无法获得对象锁,两个进程就必须串行,结论成立
- 先定义共享对象
class TestSyn {
public synchronized void func1() {
// 这个方法没有锁定,锁定的是里面的代码块