概述
java中每个对象都有一个对象监视器,对象监视器如同一把锁,具有排他性、独占性,如果线程A获取到对象监视器,则其它线程不能再对此对象进行操作,直到线程释放对象监视器。
那么如何获取对象监视器呢?援引how to own the objects monitor
A thread becomes the owner of the object’s monitor in one of three
ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
翻译过来就是
- 执行synchronized的object实例方法
- 执行synchronized(object)的同步代码块
- 对于Class类型的对象,执行这个类的静态方法
验证
下边我们将一一验证
执行synchronized的object实例方法
public class TestSynchronizedMethod {
public synchronized void m1(){
System.out.println(System.currentTimeMillis()+" m1 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m2(){
System.out.println(System.currentTimeMillis()+" m2 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void m3(){
System.out.println(System.currentTimeMillis()+" m3 method.....");
}
public static void main(String[] args) {
TestSynchronizedMethod testSynchronizedMethod = new TestSynchronizedMethod();
new Thread(new Runnable() {
@Override
public void run() {
testSynchronizedMethod.m1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
testSynchronizedMethod.m2();
}
}).start();
testSynchronizedMethod.m3();
}
}
输出结果
1576832098171 m3 method.....
1576832098171 m1 method.....
1576832103172 m2 method.....
1576832098171 -1576832103172 =5s,大约5秒后,m1释放锁后,m2才得以执行。注意因为m3未加synchronized所以不受锁影响,可并行执行。
执行synchronized的同步代码块
本种方法有点类似上一种,只是synchronized(object),object是个实例对象。
public class TestSynchronizedMethod {
private Object lock;
public TestSynchronizedMethod(Object lock){
this.lock = lock;
}
public void m1(){
synchronized (lock){
System.out.println(System.currentTimeMillis()+" m1 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void m2(){
synchronized (lock){
System.out.println(System.currentTimeMillis()+" m2 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestSynchronizedMethod testSynchronizedMethod = new TestSynchronizedMethod(new Object());
new Thread(new Runnable() {
@Override
public void run() {
testSynchronizedMethod.m1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
testSynchronizedMethod.m2();
}
}).start();
}
}
输出结果
1576832699302 m1 method.....
1576832704303 m2 method.....
同样,只有m1释放锁后,m2才得以执行。
对于Class类型的对象,执行synchronized类的静态方法
public class TestSynchronizedMethod {
public synchronized static void m1(){
System.out.println(System.currentTimeMillis()+" m1 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void m2(){
System.out.println(System.currentTimeMillis()+" m2 method.....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void m3(){
System.out.println(System.currentTimeMillis()+" m3 method.....");
}
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
TestSynchronizedMethod.m1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
TestSynchronizedMethod.m2();
}
}).start();
TestSynchronizedMethod testSynchronizedMethod = new TestSynchronizedMethod();
testSynchronizedMethod.m3();
}
}
输出结果
1576833370592 m1 method.....
1576833370593 m3 method.....
1576833375594 m2 method.....
可以看到,m1执行5秒后,m2才得以执行。虽然m3也是synchronized,但并不妨碍,也是因为m1、m2锁定的对象是TestSynchronizedMethod .class,而m3锁定的对象是testSynchronizedMethod ,锁定的不是同一个对象,所以互不影响。
经常会有人说,如果synchronized static方法,那么实例方法不能执行,这种说法是错误的!
总结
获取对象监视器,要是用synchronized关键字,synchronized方法之间是否影响要看,锁定的对象是否是同一个。