考慮如下情景:
一個class 中有一個成員變量b。
成員方法m1()爲同步方法, 並且對b進行操作。
成員方法m2()不是同步方法,並且訪問b。
那麼如果在m1() 鎖住b時 , m2()能夠執行嗎?
如果能 , 得到的b是修改前的還是修改後的呢?
如果m2()也是同步方法呢?
將上訴問題代碼化如下, 當m2()不是同步方法時:
package thread;
public class Test implements Runnable{
private int b =100;
public synchronized void m1(){
b=1000;
try{
Thread.sleep(5000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("b="+b);
}
public void m2()
{
System.out.println(b);
}
public void run(){
m1();
}
public static void main(String[] args){
Test test=new Test();
Thread t=new Thread(test);
t.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
test.m2();
}
}
此情境下,以test初始化的線程t先執行了run方法(m1), 然後主線程睡眠1秒(保證b已經被鎖住並改變成1000),之後以調用方式執行test的m2()方法。
可能發生的情況有以下幾種:
1, 報錯
2 , 先打印 b=1000 , 再打印1000 。
說明m1()執行時m2()無法執行(m2()等m1()睡眠5秒結束後才執行)
3 , 先打印 100,再打印b=1000
說明m1鎖住b的5秒內,m2()仍然可以訪問b, 得到的是b修改前的值
4 先打印 100,再打印b=1000
說明m1鎖住b的5秒內,m2()仍然可以訪問b, 得到的是b修改後的值
實際上,得到的結果如下:
1000
b=1000
說明當用synchronized修飾的方法執行時, 普通的方法時仍然可以訪問synchronized 方法中的變量的。
那麼如果 m2()也被synchronized修飾呢?
package thread;
public class Test implements Runnable{
private int b =100;
public synchronized void m1(){
b=1000;
try{
Thread.sleep(5000);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("b="+b);
}
public synchronized void m2()
{
System.out.println(b);
}
public void run(){
m1();
}
public static void main(String[] args){
Test test=new Test();
Thread t=new Thread(test);
t.start();
try{
Thread.sleep(1000);
}catch(Exception e){
}
test.m2();
}
}
結果是這樣的:
b=1000
1000
m1()執行完畢後,m2()才能夠執行。