Android多線程研究(3)——線程同步和相互排斥及死結

來源:互聯網
上載者:User

標籤:[]   技術   soc   private   com   run   cep   實現   問題   

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

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();}@Overridepublic 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被兩個線程同一時候操作。這樣就非常easy導致誤操作。

怎樣才幹解決問題呢?用線程的同步技術。加上synchronizedkeyword

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(); }}






Android多線程研究(3)——線程同步和相互排斥及死結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.