Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中多線程研究(3)——線程同步和互斥及死鎖

Android中多線程研究(3)——線程同步和互斥及死鎖

編輯:關於Android編程

為什麼會有線程同步的概念呢?為什麼要同步?什麼是線程同步?先看一段代碼:

package com.maso.test;

public class ThreadTest2 implements Runnable{
	private TestObj testObj = new TestObj();
	
	public static void main(String[] args) {
		ThreadTest2 tt = new ThreadTest2();
		Thread t1 = new Thread(tt, "thread_1");
		Thread t2 = new Thread(tt, "thread_2");
		t1.start();
		t2.start();
	}

	@Override
	public void run() {
		
		for(int j = 0; j < 10; j++){
			int i = fix(1);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println(Thread.currentThread().getName() + " :  i = " + i);
		}
		
	}
	
	public int fix(int y){
		return testObj.fix(y);
	}
	
	public class TestObj{
		int x = 10;
		
		public int fix(int y){
			return x = x - y;
		}
	}
	
	
}
輸出結果後,就會發現變量x被兩個線程同時操作,這樣就很容易導致誤操作。如何才能解決這個問題呢?用線程的同步技術,加上synchronized關鍵字

	public synchronized int fix(int y){
		return testObj.fix(y);
	}
加上同步後,就可以看到有序的從9輸出到-10.

如果加到TestObj類的fix方法上能不能實現同步呢?

	public class TestObj{
		int x = 10;
		
		public synchronized int fix(int y){
			return x = x - y;
		}
	}
如果將synchronized加到方法上則等價於

	synchronized(this){
		
	}
可以判斷出兩個線程使用的TestObj類的同一個實例testOjb,所以後實現同步,但是輸出的結果卻不是理想的結果。這是因為當A線程執行完x = x - y後還沒有輸出則B線程已經進入開始執行x = x - y.

所以像下面這樣輸出就不會有什麼問題了:

	public class TestObj{
		public TestObj(){
			System.out.println("調用了構造函數");
		}
		
		int x = 10;
		
		public synchronized int fix(int y){
			x = x - y;	
			System.out.println(Thread.currentThread().getName() + " :  x = " + x);
			return x;
		}
	}
如果將外部的fix方法修改如下:

	public int fix(int y){
		ax++ ;
		if(ax%2 == 0){
		return testObj.fix(y, testObj.str1);
		}else{
			return testObj.fix(y, testObj.str2);
		}
	}
	public class TestObj{
		String str1 = "a1";
		String str2 = "a2";
		
		public TestObj(){
			System.out.println("調用了構造函數");
		}
		
		int x = 10;
		
		public int fix(int y, String str){
			synchronized (str) {
				x = x - y;	
				System.out.println(Thread.currentThread().getName() + " :  x = " + x);
			}
			return x;
		}
	}
此時synchronized中的str對象不是同一個對象,所以兩個線程所持有的對象鎖不是同一個,這樣就不能實現同步。要實現線程之間的互斥就要使用同一個對象鎖。

什麼是死鎖呢?舉個例子就是比如你和同學租了個兩室的房子,你拿著你房子的鑰匙,你同學拿著他房子的鑰匙,現在你在房子等你同學將他的鑰匙給你然後你進他房子,你同學在他的房子等你將鑰匙給他然後他進你的房子,這樣就死鎖了。

package com.maso.test;

public class ThreadDieSock implements Runnable {
    private int flag = 1;
    private Object obj1 = new Object(), obj2 = new Object();

    public void run() {
        System.out.println("flag=" + flag);
        if (flag == 1) {
            synchronized (obj1) {
                System.out.println("我已經鎖定obj1,休息0.5秒後鎖定obj2去!");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj2) {
                    System.out.println("1");
                }
            }
        }
        if (flag == 0) {
            synchronized (obj2) {
                System.out.println("我已經鎖定obj2,休息0.5秒後鎖定obj1去!");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (obj1) {
                    System.out.println("0");
                }
            }
        }
    }

    public static void main(String[] args) {
        ThreadDieSock run01 = new ThreadDieSock();
        ThreadDieSock run02 = new ThreadDieSock();
        run01.flag = 1;
        run02.flag = 0;
        Thread thread01 = new Thread(run01);
        Thread thread02 = new Thread(run02);
        System.out.println("線程開始喽!");
        thread01.start();
        thread02.start();
    }
}





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