1. 程式人生 > >synchrozied方法和synchrozied修飾代碼塊的區別

synchrozied方法和synchrozied修飾代碼塊的區別

tst img 分析 name highlight string targe ack odi

synchroized是jvm提供的,無需手動控制它可以自動對多線程訪問的資源進行加鎖與解鎖,它可以修飾方法,也可以修飾代碼塊.

這邊博客記錄下個人對synchrozied的理解如下:

1.為什麽Java要提供synchronized?

  當多條線程去對一個類的實例變量進行修改,這時會發生變量的不確定性.為解決這個問題,使用synchronized修飾,使得在某一時刻,只能有一條線程進行操作.實現的方式是加鎖與解鎖.

2.實例演示多線程訪問共享變量產生的問題.  

public class ManyThreadModify implements Runnable{

private int value = 10;

@Override
public void run() {
for(int i = 0; i < 10; i++) {
value--;
System.out.println(Thread.currentThread().getName() + "修改value的值為:" + value);
}
}

public static void main(String[] args) {
ManyThreadModify mm = new ManyThreadModify();
//使用實現Runnable接口的方式可以共享變量,每啟動的線程都是以target形式啟動的

new Thread(mm , "線程01").start();
new Thread(mm , "線程02").start();
}
}

技術分享圖片 可以看到,出現了value的值兩次等於8的情況,這就是線程不安全造成的,在run方法上加上synchronize修飾可以解決這個問題.

3.synchrozied修飾方法和修飾代碼塊的區別

  修飾方法:synchronize public void test(){}

  修飾代碼塊:synchronize(鎖對象){  //代碼塊 }

  區別:

public class SynchronizedMethodAndCode{
	//synchronize修飾方法
	public synchronized void test01() {
		try {
			System.out.println("this is method test01...");
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	public void test02() {
		//synchronize修飾代碼塊,鎖對象為當前對象
		synchronized (this) {
			System.out.println("this is method test02...");
		}
	}
	public void test03() {
		String str = "s";
		//synchronize修飾代碼塊,鎖對象為str
		synchronized (str) {
			System.out.println("this is method test03...");
		}
	}
}

  啟動線程訪問

public class SynchroziedMain {

	public static void main(String[] args) {
		SynchronizedMethodAndCode sc = new SynchronizedMethodAndCode();
		//啟動線程1訪問test01方法
		new Thread(new Runnable() {
			@Override
			public void run() {
				sc.test01();
			}
		}).start();
		
		//啟動線程2訪問test02方法
		new Thread(new Runnable() {
			@Override
			public void run() {
				sc.test02();
			}
		}).start();
		
		//啟動線程3訪問test03方法
		new Thread(new Runnable() {
			@Override
			public void run() {
				sc.test03();
			}
		}).start();
	}
}

  可以看到打印結果,

技術分享圖片

分析:啟動線程1訪問test01方法時遇到sleep(3000),線程1沒有釋放鎖資源,在這裏,鎖資源就是當前對象,鎖被線程1拿在了手裏沒有釋放,而test02方法的鎖對象this也是當前對象,所以線程1和線程2使用的是同一把鎖,線程2等待線程1     sleep()結束才能獲得鎖,進入test02方法的打印代碼中,所以線程3先打印了,因為它的鎖是自己定義的一個String對象.

總結:synchronize修飾方法的鎖對象只能是this當前對象

   synchronize修飾代碼塊可以修改鎖對象

 

synchrozied方法和synchrozied修飾代碼塊的區別