none
在 multi-threads 上的疑問 RRS feed

  • 問題

  • Dear all,

    當 static  util class(如: Class1)在多執行緒環境執行時,是否有 sync 的問題?
    public class Class1 {
        private Class1() {
        }
    
        public static String Method1(int input) {
            int output = null;
            if(input == 1) {
                output = "a";
            } else if(input == 2) {
                output = "b";
            } else if(input == 3) {
                output = "c";
            }
            return output;
        }
    }

    假設有兩個以上的 clients 分別呼叫Class1 的 Method1,比如:
     client1 執行 Class1.Method1(1);
     client2 執行 Class1.Method1(2);
      ...
    那麼會不會有一種狀況是,
    當 client1 已經執行 Method1(1) 但還未跑到 return output,在此時 client1 執行 Method1(2),
    那麼 client1 取得的結果會不會有可能是 "b"? 造成 object 有 sync 的問題。


    此狀況在 Singleton class 上是否也會發生?
    比如:
     client1 執行 Class1.GetInstance().Method1(1);
     client2 執行 Class1.GetInstance().Method1(2);
     ...


    謝謝
    2009年8月6日 上午 05:05

解答

  • 1.所謂MultiThread的衝突問題指得是資料並非程式
    在你的範例中input與output是區域變數,並不會有交互影響問題.
    所以MultiThread避免麻煩的設計原則中,第一條就是盡量使用區域變數.如果真得無法使用區域變數,通用變數部分無論如何最好都用MultiThrad的同步機制來處理所有的變數,因為不論如何你很難確保這些變數不會有資料衝突與同步問題.

    2.Singleton class 指得是class本身並不會產生兩個實體(instance),但如果Singleton class 內的程式有使用非區域變數或成員變數就有可能會發生衝突同步問題.


    綜合以上結論就是會影響MultiThread最大的原因就是通用變數導致共用衝突或同步,而deadlock如果嚴格說起來也是通用資料問題導致

    • 已標示為解答 Kalin Chih 2009年8月6日 上午 06:59
    2009年8月6日 上午 05:24

所有回覆

  • 1.所謂MultiThread的衝突問題指得是資料並非程式
    在你的範例中input與output是區域變數,並不會有交互影響問題.
    所以MultiThread避免麻煩的設計原則中,第一條就是盡量使用區域變數.如果真得無法使用區域變數,通用變數部分無論如何最好都用MultiThrad的同步機制來處理所有的變數,因為不論如何你很難確保這些變數不會有資料衝突與同步問題.

    2.Singleton class 指得是class本身並不會產生兩個實體(instance),但如果Singleton class 內的程式有使用非區域變數或成員變數就有可能會發生衝突同步問題.


    綜合以上結論就是會影響MultiThread最大的原因就是通用變數導致共用衝突或同步,而deadlock如果嚴格說起來也是通用資料問題導致

    • 已標示為解答 Kalin Chih 2009年8月6日 上午 06:59
    2009年8月6日 上午 05:24
  • Dear programlin,

    感謝你清楚的解答, 小弟想到另一個問題,

    所以這個例子裡,
    是否 Class1 再處理多個 clients 的呼叫, 都會在記憶體產生各自的 Method1() 區塊來處理個各個 threads 的運作?

    謝謝
    2009年8月6日 上午 05:45
  • 我的答案是全部都會.
    因為妳的是靜態方法.所以整支程式就只有一個實體.
    你很多Thread去存取同一個靜態方法.Thread會去排優先權去存取.
    如果你靜態方法裡,有個變數讓多個Thread去存取時就可能發生問題.
    2009年8月6日 上午 05:57
  • >>所以這個例子裡,
    >>是否 Class1 再處理多個 clients 的呼叫, 都會在記憶體產生各自的 Method1() 區塊來處理個各個 threads 的運作?


    這個問題其實上面已經回答了
    程式碼不論你有多少個實體,及與Static或private,protected,public...皆無關,程式碼所佔用的記憶體永遠只有一份.
    真正會變動的是 "資料"
    舉例來說
     class A
    {
    int i1;
    int i2
    public int Fun()
    {
    return i1 +i2;
    }
    }

    A a = new A();
    A b = new A();


    這個結果Fun在記憶體中只會佔據一份不論你new了多少個instance,而a跟b明確的說是各自擁有i1與i2.
    所以new這個動作是在建立個別的資料部分記憶體配置,也就是所謂的instance.


    2009年8月6日 上午 06:06
  • 舉一個我認為會影響的範例.

    public class Demo{
            private static int lock;
            public int Fun()
            {
                 //對lock 作運算
             }
    }

    你new 二個實例.給二Thread去跑.二個實例可能存取同一個靜態變數.
    當然這個發生機率很低,因為複雜度不夠.

    比較會發生問題的是 UIThread.因為你給個BackgroudThread時,前端的UI是計算很複雜的事,他會不斷的算畫面,不斷的監聽Keyboard,Mouse..活動.所以你Backgroud 將結果送到UI的某控制項,某變數,這個變數可能被UI端程序執行中就會發生問題.
    2009年8月6日 上午 06:20
  • 謝謝回答,
    另外我在網路上也找到蔡老師之前寫的相關的文章,
    http://www.oreilly.com.tw/column_sleepless.php?id=j021

    http://forums.sun.com/thread.jspa?threadID=5350276
    2009年8月6日 上午 07:01