當同步方法被鎖住時,非同步方法是否可以訪問同步方法中改變的變量?


考慮如下情景:

  一個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()才能夠執行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章