2012-03-05 189 views
12

我可以安全地嘗試從兩個不同的線程創建相同的目錄,但沒有其中一個拋出異常,或遇到其他問題?是C#中的CreateDirectory()線程安全嗎?

注意的是,根據MSDN,這是確定調用CreateDirectory()上已經存在的目錄,在這種情況下,該方法有望無可奈何。

回答

13

調用本身可以安全地從多個線程中調用。如果你這樣做,它不會損壞程序或文件系統狀態。

但是不可能以這種方式調用Directory.CreateDirectory以保證它不會拋出異常。文件系統是一個不可預知的野獸,在任何給定的時間內,您可以通過其他程序對其進行更改。這是非常可能的例子來看看下面發生

  • 計劃1線程1:調用CreateDirectoryc:\temp\foo並且取得了成功
  • 計劃2線程1:從程序1用戶
  • 計劃1線程刪除要c:\temp訪問2:呼叫CreateDirectory並且由於沒有足夠的訪問

拋出總之你必須假定Directory.CreateDirectory,還是真的其中涉及文件系統中的任何功能,能夠而且將會ŧ相應地進行伸縮和處理。

6

MSDN docs on Directory

任何公共靜態此類型的成員(在Visual Basic中的Shared)都是線程安全的。任何實例成員不保證是線程安全的。

因此,由於CreateDirectory是靜態的,所以它是線程安全的。

也就是說:正如@JaredPar指出的,線程安全問題不是方法拋出異常的唯一原因。文件系統調用可能會引發異常(在任何情況下,多線程或不)的原因有很多,您需要考慮這些原因。我的(和MSDN)只意味着它的字面解釋,意思是「這種方法不會修改共享程序狀態,導致無效狀態,競態條件或其他不利影響通常與不安全的多線程代碼相關聯「

+0

這並沒有解決問題,但它是否會拋出一個或兩個線程 – JaredPar 2012-03-05 19:44:33

+0

真的 - 我相信你的答案覆蓋更好(我upvoted btw)。我會修改我的答案。 – 2012-03-05 19:55:33

4

爲了闡述@ JaredPar的答案,你的手上有一個競爭條件。如果第一個電話完全創建文件夾,只有第二個電話開始,一切都會好的。但是,如果第二次調用在操作系統仍在處理第一個調用時到達操作系統,則操作系統可能會失敗,第二個沙丘會出現鎖定問題,您將得到一個異常。

它仍然是線程安全的,因爲您不會得到任何不可預知的文件夾創建,或根本沒有文件夾。

要闡述 - 而我不是100%肯定,Windows不具備當同一文件夾中創建同時兩次內部競爭,我敢肯定,你將無法通過向垃圾盤這樣做,或者兩個創作都陷入死亡而陷入僵局。其中一人會成功,對方會失敗,但該文件夾將被創建。

所以,你的啓發,只是絕對肯定,應該是這樣的:

  • 創建目錄
  • 如果失敗,等待一段隨機時間(比如0.2秒到0.5之間)然後再試一次。
  • 如果它不斷失敗(比如,連續3次),你必須在你的手中了另一個問題 - 沒有權限的文件夾,一個完整的磁盤等。

    順便說一下,爲什麼無法創建文件夾一旦應用程序開始運行?

+0

你確定嗎?我的目的是有幾個不同的線程創建(獨立的),在相同的日誌文件的目錄,如果需要創建它。假設你是正確的,並創建文件夾不是一個原子操作,我必須使用(例如)一個鎖來進行同步。什麼是關於CreateDirectory()的「線程安全」呢? – bavaza 2012-03-06 07:38:31

+0

我會詳細說明。 – zmbq 2012-03-06 07:40:30

+0

謝謝。我認爲這可能是我看到的行爲。 – 2016-08-05 17:19:55