Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 以Android環境為例的多線程學習筆記(二)-----------------鎖和條件機制

以Android環境為例的多線程學習筆記(二)-----------------鎖和條件機制

編輯:關於Android編程

現在的絕大多數應用程序都是多線程的程序,而當有兩個或兩個以上的線程需要對同一數據進行存取時,就會出現條件競爭,也即

是這幾個線程中都會有一段修改該數據狀態的代碼。但是如果這些線程的運行順序推行不當的話是很容易造成死鎖現象的。所以在JAVA中為

了防止出現這種現象的出現就產生了鎖和條件機制用來對實現各個線程之間互斥的去訪問這段臨界區的代碼,唉!由於我也是才剛學多線程

並發編程,也不可能有多深多深的理解,所以就先只寫一下它們的用法了。

------------------YYC

其實從JAVA SE 5.0以後就有兩種機制來防止代碼塊受並發訪問的干擾,一種是通過lock機制,另一種是通過synchronized來實現,

下面分別來實現。


該部分程序的功能主要是實現通過多個線程 去訪問yy和cc這兩個變量,然後在每個線程中都分別不斷的從其中一個大於0 的變量中減去10,然

後在給另外的一個變量加上10,如果說此處不用鎖的機制去實現線程的修改yy和cc時,是恆容易發生死鎖錯誤的,而且在運行一段時間後yy和cc

的總和也將不再是100.

方法一:

public int  yy = 0;
public int  cc =100;

public class YYThread extends Thread{
                private Condition condition ;  //定義條件對象
		private Lock YYlock = new ReentrantLock(); //定義鎖對象,
//其中ReentrantLock()方法是用來構造一個用來保護臨界區的可以重入鎖,此處也可以調用ReentrantLock(boolean fair)來構造一個公平鎖

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			    YYlock.lock();//當線程運行到這個地方時給下面的代碼片加上互斥鎖
			    condition = YYlock.newCondition();  //初始化條件對象
			    Random random  = new Random();
			    int a =   random.nextInt();
			    int b = a%2;
			    if(b==0)
			    {
			    	if(yy<10)
			    	{try {
						condition.await();//當發現該線程的條件不足時,自動阻塞當前線程,並釋放處理機等資源和解鎖臨界資源
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}}
			    	yy-=10;
			    	cc+=10;
			    	Log.d("yy   "+yy, "cc   "+cc);
			    	condition.signalAll();//當資源狀態改變時,調用該方法解除所有因這一條件而等待的所有線程,當這些線程從等待集裡移除時。它們就
//再次成為可運行的,相當於是處於就緒狀態,調度器就可再次激活他們。
			    }
			    else {
			    	if(cc<10)
			    	{try {
						condition.await();
//當發現該線程的條件不足時,自動阻塞當前線程,並釋放處理機等資源和解鎖臨界資源
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}}
					yy+=10;
					cc-=10;
					Log.d("yy   "+yy, "cc   "+cc);
					condition.signalAll();//激活其他線程
				}
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();}
			finally{
				 YYlock.unlock();
                             //解鎖對該部分代碼的訪問控制,注意此解鎖操作必須要放在finally字句裡面,因為如果臨界區的代碼拋出異常的話,鎖必須要被
//釋放,否則其他所有線程都將永遠阻塞

			}
	
		}
	
	} 


調用部分

//實現方式一:
			for(int i =0 ;i<80;i++)
			{
			YYThread yt = new YYThread();
			yt.start();
			}


成功實現鎖和條件的機制鎖主要是原來實現保護臨界區的代碼片,實現互斥的相互訪問
條件主要是用來管理進入臨界區的線程condition.await();進入條件的等待集, 該線程被阻塞,

並自動放棄處理機資源和解鎖臨界資源,但它與互斥阻塞的主要區別是只要
當condition.signalAll();激活該該線程時,該線程將立馬成為可運行的,並接受調度器的調度。
YYlock.lock();互斥阻塞,當獲得臨界資源時才可能被執行


方法二:

定義該方法

public int  yy = 0;
	public int  cc =100;
	private synchronized void fun()//用關鍵字synchronized聲明為該方法只能互斥訪問
	{   Random random  = new Random();
	    int a =   random.nextInt();
	    int b = a%2;
	    if(b==0)
	    {    
	    	while(yy<10)
				{try {
					wait();//條件阻塞
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}}
	    	yy-=10;
	    	cc+=10;
	    	notifyAll();//激活阻塞隊列的線程
	    	Log.d("yy   "+yy, "cc   "+cc);
	    }
	    else {
	    	while(cc<10)
				{try {
					wait();//用while循環檢測條件,但也會遵循“讓權等待”的原則。
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}}
			 cc-=10;
			 yy+=10;
			 notifyAll();//激活阻塞隊列的線程
			 Log.d("yy   "+yy, "cc   "+cc);
		}
	}

定義線程

public class YYThread extends Thread{
		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			  
			fun();
			
		}
	} 

開啟線程

			for(int i =0 ;i<80;i++)
			{
			YYThread yt = new YYThread();
			yt.start();
			}

其實方法一和方法二的效果都是一樣的,但是我們可以看到使用synchronized關鍵字來編寫代碼要簡潔的多,但是如果你要理解這一關鍵字的機制,你就必須了解

其實每一個對象都是有一個內部鎖的,並且該鎖有一個內部條件,由鎖來管理那些試圖進入synchronized方法的線程,由條件來管理那些調用wait的線程。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved