要弄懂java的同步机制,就得先明白java的内存模型。
锁是是针对对象的,所以同步是同步整个对象上的同步方法或代码,不要被加锁方法所误导
下面两个代码是等价的,都是对同一个对象加锁,不同的是,test1是在 被调用后对this加锁,而test2是在调用方法的时候对this加锁。
public class TestSynch{
public void test1(){
synchronized(this){
Thread.sleep(1000);
//System.out.println("test1");
}
}
public synchronized void test2(){
Thread.sleep(1000);
//System.out.println("test2");
}
}
调用加锁的对象的方法会被阻塞吗?
将上面的代码修改如下:
public class TestSynch{
public void test1(){
synchronized(this){
Thread.sleep(1000);
test2();
System.out.println("test1");
}
}
public synchronized void test2(){
Thread.sleep(1000);
System.out.println("test2");
}
}
测试:
TestSynch t = new TestSynch();
//t对象将会被线程1上锁
new Thread(t::test1).start();
//保证线程1优先执行在线程2之前
Thread.sleep(1);
//由于t对象被线程1上锁,所以线程2调用t的同步方法将会被阻塞
new Thread(t::test2).start();
//线程3调用的是t的非同步方法,所以不受锁的限制
new Thread(t::toString).start();
执行流程图:
答:
1. 获得当前对象锁的线程,再调用加锁的方法,不会阻塞,比如线程1
2. 调用该对象普通方法(即没有同步的方法),不会阻塞,比如线程3
3. 既没有获得锁,调用的又是同步方法或代码块,会被阻塞,比如线程2