close

※情境:  以執行緒模擬出貨進貨之情形,最終一筆資料為最初數量。

●模擬情形:

public class AddStockThread extends Thread {

    public AddStockThread() {
    }
    
    private Material m;

    public AddStockThread(Material m) {
        this.m = m;
    }

    @Override
    public void run() {
        for(int i =0;i<10000;i++){
            m.addStock(1);
        }
    }
}
 

public class SubtractStockThread extends Thread {

    public SubtractStockThread() {
    }
    private Material m;

    public SubtractStockThread(Material m) {
        this.m = m;
    }

    @Override
    public void run() {
        for(int i =0;i<10000;i++){
            m.addStock(-1);
        }
    }
}


public class Material {
    private int stock;
    public  void addStock(int i){
        int j = this.stock;
        j = j + i;
        for(int x = 0;x < 100000;x++){ }
        this.stock = j;
        System.out.println("stock=" + stock);
    }
    public void setStock(int stock){
        this.stock = stock;
    }
    public int getStock(){
        return this.stock;
    }
}

public class Test0610 {
    public static void main(String[] args) {
        Material m = new Material();
        m.setStock(10000);
        AddStockThread add = new AddStockThread(m);
        SubtractStockThread sub = new SubtractStockThread(m);
        add.start();
        sub.start();
    }
}
 

Out:   這樣跑起來,因為執行緒由作業系統決定順序,兩個執行緒會互相搶;在加上大量資料同時處理,所以最後筆資料不是固定的。


●解決方案:

     --透過synchronized

●模式一:

     --synchronized{物件}{....}

●模式二:

     --public synchronized void f1() {....}

※模式一:

public class Material {
    private int stock;
    public void addStock(int i){
        synchronized(this){                          //只允許一次進來一個
        int j = this.stock;
        j = j + i;
        for(int x = 0;x < 100000;x++){   }
        this.stock = j;
        System.out.println("stock=" + stock);
        }
    }
    public void setStock(int stock){
        this.stock = stock;
    }
    public int getStock(){
        return this.stock;
    }
}
 

※模式二

public class Material {
    private int stock;
    public synchronized void addStock(int i){
        int j = this.stock;
        j = j + i;
        for(int x = 0;x < 100000;x++){  }
        this.stock = j;
        System.out.println("stock=" + stock);
    }
    public void setStock(int stock){
        this.stock = stock;
    }
    public int getStock(){
        return this.stock;
    }
}

※總結:

●哪個比較好?

●建議模式一

   --鎖定的時間短,但有機率DeadLock

●什麼是DeadLock

   -- 所謂的死結,是指兩個執行緒分別取得了鎖定,互相等待另外一個執行緒解除鎖定的現象,發生死結的時候,哪個執行緒都無法繼續執行下去,這時候程式就會不斷等待。

●如何解決DeadLock

   -- 參考資料:http://twmht.github.io/blog/posts/multithread/deadlock.html


※Problems with Shared Data

●在執行緒中共享資料,且能保證安全存取是工程師的責任。

※Out-of-Order Excel

●每一支Thread會從主記憶體複製一份資料到自己的工作區(working momory),並且操作工作區內的資料。

●以下方式都可以將Thread工作區內的資料與主記憶體內資料同步

    --利用 volatile 保留字來修是變數

    --利用 synchronized 保留字來鎖定/解鎖

    --Thread 內的第一及最後一個動作

    --啟動執行緒或執行緒已結束時

arrow
arrow
    文章標籤
    synchronized DeadLock
    全站熱搜
    創作者介紹
    創作者 淺翔 的頭像
    淺翔

    翔の學習淺談

    淺翔 發表在 痞客邦 留言(0) 人氣()