2016-11-30 11 views
-3

我已經閱讀了很多關於這個問題的文章或者其他的文章,但是還是找不到真正的答案。根據這些答案,(靜態/實例)方法內創建的所有變量應該是線程安全的。不幸的是,這不能正常工作。爲什麼只有在線程之間共享的靜態方法中使用任何變量?

我有這樣的代碼:

public static void TestThreadSafetyOfInsideVariableOfStaticMethod() 
{ 
    Thread t1 = new Thread(staticClass.Test) { Name = "t1" }; 
    Thread t2 = new Thread(staticClass.Test) { Name = "t2" }; 
    Thread t3 = new Thread(staticClass.Test) { Name = "t3" }; 
    Thread t4 = new Thread(staticClass.Test) { Name = "t4" }; 

    t1.Start(); t2.Start(); t3.Start(); t4.Start(); 
} 


public static class staticClass 
{ 
    public static void Test() 
    { 
     for (int i = 1; i < 11; i++) 
     { 
      FileStream fs = new FileStream("C:\\test.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite); 
      byte[] bytesToWrite = Encoding.UTF8.GetBytes(Thread.CurrentThread.Name + " is currently writing its line " + i + ".\r\n"); 
      fs.Write(bytesToWrite, 0, bytesToWrite.Length); 
      fs.Close(); 
      fs.Dispose(); 
      Thread.Sleep(500); 
     } 
    } 
} 

當我運行TestThreadSafetyOfInsideVariableOfStaticMethod,然後在文本文件中的輸出是這樣的:

T2目前正在寫它的1號線
T3目前正在撰寫其行1.
t4目前正在寫它的行1.
t1正在寫它的行2.
t2正在寫入制定其下屬線2
T4當前正在寫入其線2
T2當前正在寫入其線3
T1當前正在寫入其線3
T4當前正在寫入其線3
t4爲當前寫入其線4
T4當前正在寫入其線5
T1當前正在寫入其線6
T1當前正在寫入其線7
T1當前正在寫入其線8
t2爲當前寫它的李NE 9.
T1當前正在寫入其線9
T3當前正在寫入其線9
T4當前正在寫入其線10
- 文件的末尾。

我期望每個線程都會在自己的for循環中寫入自己的行,所以有40行,不會在方法內的for循環中共享「i」變量。爲什麼他們分享這個「我」變量?

我是否必須鎖定整個項目中的所有靜態方法?那麼參數呢,線程也會共享它(我不會顯示代碼,但我已經測試過了)。

+0

'i'不會被共享。無論這裏有什麼問題,都必須有另一個原因。 –

+0

你的代碼不是Java。 –

+1

全部4個主題*都是* '線4',但他們在同一時間做到這一點,即他們都開在同一時間'Append'文件,這意味着他們都將自己定位在文件中的同一個點,然後他們都寫入到文件,'t4'寫完最後一個,覆蓋其他3個線程寫的內容。爲了防止這種情況,您需要控制對共享資源的訪問。 – Andreas

回答

4

問題不是共享變量i,而是共享文件"C:\\test.txt"。你有四個線程同時寫入。其實完全圍繞這些寫入沒有同步,所以當多個線程嘗試添加自己"tX is currently writing its line Y",一個是要贏,而其餘的會看到他們的產量下降。

您可以通過訪問該文件,以防止同時追加時建立的線程之間的適當的同步解決這個問題。

+0

每行都有一個明確的Close + Dispose。 –

+0

@HenkHolterman哎呀,我錯過了,因爲他們都在同一行。感謝您的指出,我編輯了這個問題以使Close + Dispose突出。 – dasblinkenlight

+0

好的,所以你的意思是所有的線程都檢查文件的大小,並開始寫在這個地址(最後),所以它可以被其他線程重寫? – Driver

相關問題