Single Threaded Execution Pattern

Single Threaded Execution Pattern

是指我們的方法限定一次只能由一個執行緒所執行。

假設我們有一個Gate,一次只能夠限定一個人通過,現在我們有多個人(多個thread)要通過這個門,每次通過之後Gate會顯示通過的人的name以及address,同時Gate會用一個counter來紀錄目前有多少人通過。

Gate.java

    public class Gate {
    private int counter = 0;
    private String name = "Nobody";
    private String address = "Nowhere";
    //加入synchronized限制一次只能由一個thread來執行這個pass
    public synchronized void pass(String name, String address) {
        this.counter++;
        this.name = name;
        this.address = address;
        check();
    }
    public synchronized String toString() {
        return "No." + counter + ": " + name + ", " + address;
    }
    private void check() {
        if (name.charAt(0) != address.charAt(0)) {
            //表示shared resource有同時讓不同的thread更改過,同時也代表這不是thread-safe
            System.out.println("***** BROKEN ***** " + toString());
        }
    }
}

Main.java

    public class Main {
    public static void main(String[] args) {
        System.out.println("Testing Gate, hit CTRL+C to exit.");
        Gate gate = new Gate();
        new UserThread(gate, "Alice", "Alaska").start();
        new UserThread(gate, "Bobby", "Brazil").start();
        new UserThread(gate, "Chris", "Canada").start();
    }
}

UserThread.java

    public class UserThread extends Thread {
    private final Gate gate;
    private final String myname;
    private final String myaddress;
    public UserThread(Gate gate, String myname, String myaddress) {
        this.gate = gate;
        this.myname = myname;
        this.myaddress = myaddress;
    }
    public void run() {
        System.out.println(myname + " BEGIN");
        while (true) {
            gate.pass(myname, myaddress);
        }
    }
}

Single Thread Execution Pattern的概念較為簡單,我們把Gate當作SharedResource,在一般情況下,SharedResource會被多個執行緒所存取,SharedResource會有一些方法,這些方法又可以分為safeMethod以及unsafeMethod。

  • safeMethod: 讓多個執行緒同時存取也不會有問題。
  • unsafeMethod: 讓多個執行緒同時存取會有問題,因此可以考慮加上synchronized,讓unsafeMethod只能同時被一個執行緒所存取。我們又可以稱加上synchronized的方法為critical section。

至於為什麼check()這一個方法不需要加上synchronized,因為check()在pass()中被呼叫,而pass()又是synchronized的方法,因此可以保證同時只會有一個執行緒去執行check()。