2011-05-28 131 views
2

我有實例從這樣的類:線程之間共享一個方法的局部變量嗎?

public class One 
{ 
    Semaphore S = null; 
    public One(Semaphore S) 
    { 
     this.S = S; 
    } 
    public void Run(int ID) 
    { 
     S.WaitOne(); 
     Console.WriteLine("Thread [" + ID + "] Entered"); 
     Random R = new Random(); 
     Thread.Sleep(R.Next(100, 1000)); 
     Console.WriteLine("Thread [" + ID + "] Exited"); 
     S.Release(); 
    } 
} 

在我的節目我實例化了幾個新的線程。每個線程運行上述類中的「Run()」方法。

Semaphore S = new Semaphore(5, 5); 
One O = new One(S); 
for (int j = 0; j < 10; j++) 
{ 
    Thread T = new Thread(delegate() { O.Run(j); }); 
    T.Start(); 
} 

我希望看到一個從0到9的數字列表,但是沒有排序。但是我的結果顯示「Run()」方法中的「ID」變量作爲局部變量在所有線程之間共享。

![Output][1] 

我想知道,如果我有一個類的一個實例,很多線程從實例中運行的方法,所以在所有線程之間共享該方法的局部變量?或者每個線程都有自己的本地副本?我應該爲該類的每個線程創建一個新實例嗎?

+0

我認爲它不是共享的ID變量,但是從環Ĵ..我認爲這是通過引用傳遞給代表,所以他們都看到相同的.. – xs0 2011-05-28 13:03:03

+0

... *刪除* ... – DarkSquirrel42 2011-05-28 13:08:27

回答

6

不,局部變量不在線程之間共享。而你的參數ID是這方面的一個局部變量。它不共享。

您看到的是由標準問題捕獲的迴路var引起的。這是簡單的一個額外的變量來解決:

for (int j = 0; j < 10; j++) 
{ 
    int copy = j; 
    Thread T = new Thread(delegate() { O.Run(copy); }); 
    T.Start(); 
} 

,我希望這表明那裏的問題是:j變量由您的匿名方法捕獲,實際上這意味着它是由所有的共享(通過參考) O.Run()的呼叫站點。

+0

+1,因爲這將救我從各種無效(對象)方法... – DarkSquirrel42 2011-05-28 13:19:25

1

不,當地人不會在線程之間共享。如果您正在調試線程,請務必打開線程窗口,以便您可以在線程之間切換,以查看變量。否則,如果手錶卡在一根線上,可能會產生誤導性結果。

我在程序的一次運行中得到以下輸出,但由於它的本性,每次都可以得到不同的結果。

Thread [1] Entered 
Thread [2] Entered 
Thread [4] Entered 
Thread [4] Entered 
Thread [5] Entered 
Thread [2] Exited 
Thread [1] Exited 
Thread [10] Entered 
Thread [6] Entered 
Thread [6] Exited 
Thread [10] Exited 
Thread [9] Entered 
Thread [8] Entered 
Thread [4] Exited 
Thread [5] Exited 
Thread [8] Entered 
Thread [4] Exited 
Thread [8] Exited 
Thread [9] Exited 
Thread [8] Exited 
1

試試這個:

static void Main(string[] args) 
{ 
    Semaphore S = new Semaphore(5, 5); 
    One O = new One(S); 
    for (int j = 0; j < 10; j++) 
    { 
     Thread T = new Thread(new ParameterizedThreadStart(O.Run)); 
     T.Start(j); 
    } 
} 

public class One 
{ 
    Semaphore S = null; 
    public One(Semaphore S) 
    { 
     this.S = S; 
    } 
    public void Run(object ID) 
    { 
     // int id = (int) ID; // when you need an int 
     S.WaitOne(); 
     Console.WriteLine("Thread [" + ID + "] Entered"); 
     Random R = new Random(); 
     Thread.Sleep(R.Next(100, 1000)); 
     Console.WriteLine("Thread [" + ID + "] Exited"); 
     S.Release(); 
    } 
} 
0

沒有,既沒有局部變量,也不是方法的參數線程之間共享。你所看到的是因爲變量j在你創建的匿名代表之間共享。因此,對於您的情況,有一個全局變量j,每個線程的Run()都會獲取變量在調用該方法時的值,這可能是j在下一次迭代中增加後的值。

您可以通過創建一個新的變量解決這個問題,那就是「本地」每次迭代:

for (int j = 0; j < 10; j++) 
{ 
    int tmp = j; 
    Thread T = new Thread(delegate() { O.Run(tmp); }); 
    T.Start(); 
}