1. 程式人生 > >對java中File.mkdirs方法執行緒安全問題的一點探討

對java中File.mkdirs方法執行緒安全問題的一點探討

mkdirs是java中用來一次建立多級目錄的方法,在java.io.File類中。

我在程式設計中遇到這樣一段程式碼:
    if (!dest.exists()) {
        dest.mkdirs();
    }
    if (!dest.isDirectory()) {
      throw new IOException(dest.getName() + " must be a directory!");
    }

該段程式碼所在的方法會被多個執行緒呼叫。在某些次的執行中,dest.mkdirs方法建立目錄就會失敗,從而造成下面的if語句裡的拋異常程式碼被執行。

JDK 1.5 update 21中的java.io.File.mkdirs程式碼如下:
    public boolean mkdirs() {
         if (exists()) {
             return false;
         }
         if (mkdir()) {
            return true;
        }
        File canonFile = null;
        try {
            canonFile = getCanonicalFile();
        } catch (IOException e) {
            return false;
        }
         String parent = canonFile.getParent();
        return (parent != null) &&
               (new File(parent, fs.prefixLength(parent)).mkdirs() &&
                                    canonFile.mkdir());
    }

考察該mkdirs原始碼,發現在這種可能的情形中,會出問題:兩個執行緒都呼叫最前面那段程式碼,第一個執行緒中要建立的目錄為“dirParent/dirA”,第二個執行緒要建立的目錄為“dirParent/dirB”(執行以前dirParent目錄不存在)。這兩個執行緒都進入mkdirs方法,兩個執行緒都沒能直接建立目錄並執行到“return”語句那一行,接下來,第一個執行緒執行完畢併成功建立了“dirParent/dirA”目錄,這時第二個執行緒向前推進,對mkdirs方法的遞迴呼叫由於“dirParent”目錄已存在而返回false,由“&&”運算子的短路機制,“canonFile.mkdir()”語句將不會被執行,也就是說“dirB”目錄並沒有被創建出來,且此時mkdirs也將返回false。於是,在第二個執行緒中,後面的丟擲異常的語句就被執行。

這樣看來,mkdirs方法並不是執行緒安全的。針對這段程式的實際情況,我將最上面的程式碼改成下面這樣(FileUtils是該段程式碼所在的類,且該段程式碼所在的方法為靜態方法):
    if (!dest.exists()) {
        synchronized (FileUtils.class) {
            dest.mkdirs();
        }
    }
    if (!dest.isDirectory()) {
      throw new IOException(dest.getName() + " must be a directory!");
    }
這樣,問題就解決了。

相關推薦

javaFile.mkdirs方法執行安全問題的一點探討

mkdirs是java中用來一次建立多級目錄的方法,在java.io.File類中。 我在程式設計中遇到這樣一段程式碼:    if (!dest.exists()) {        dest.mkdirs();    }    if (!dest.isDirectory

java為什麼Hashtable是執行安全的,而HashMap是執行安全的?還有ArrayList為什麼是執行安全的,Vector是執行安全的??

文章目錄 一、HashMap解析 二、Hashtable解析 三、Collections.synchronizedMap()解析 四、ConcurrentHashMap 六、ArrayList為什麼是執行緒不安全的,Vector是執行緒安全的?

java那些類是執行安全的?

Java中各種集合(字串類)的執行緒安全性!!!   一、概念: 執行緒安全:就是當多執行緒訪問時,採用了加鎖的機制;即當一個執行緒訪問該類的某個資料時,會對這個資料進行保護,其他執行緒不能對其訪問,直到該執行緒讀取完之後,其他執行緒才可以使用。防止出現數據不一致或者資料被汙染的情況。

javafinal與volatile-執行安全問題

線上程安全問題中final主要體現在安全釋出問題上,在這裡先講一下什麼事安全釋出,在《java併發程式設計實踐》一書中有講,不過看起來挺難懂的…. public class Holder { private int n;

JAVAArrayList如何保證執行安全

保證執行緒安全的三種方法:不要跨執行緒訪問共享變數 使共享變數是final型別的 將共享變數的操作加上同步 一開始就將類設計成執行緒安全的, 比在後期重新修復它,更容易. 編寫多執行緒程式, 首先保證它是正確的, 其次再考慮效能. 無狀態或只讀物件永遠是執行緒安全的.

java,多個執行同時呼叫同一個靜態方法的問題

我的原來程式是這樣設計的,對於一些常用的方法,都用靜態方法來實現,在多執行緒程式中直接呼叫,靜態方法由於沒有使用靜態變數,所以沒有進行執行緒同步。 類似以下程式: class ThreadI { public static void main(String[] arg) {

java開啟一個新執行

//實現方法pubRmRecordByRmPlanId @Override public OperateResult pubRmRecordByRmPlanId(Long rmPlanId,String taskBeginDate,UserInfo userInfo) { ...

Java建立和啟動執行的兩種方式

方式1:繼承Thread類 步驟: 1):定義一個類A繼承於java.lang.Thread類. 2):在A類中覆蓋Thread類中的run方法. 3):我們在run方法中編寫需要執行的操作:run方法裡的程式碼,執行緒執行體. 4):在main方法(執行緒)中,建

淺析Java的四種執行

1.使用執行緒池的好處    2.JUC中幾種常用的執行緒池 java.util.concurrent包下的Executors工廠類,提供了一系列的執行緒池的建立方法,其構造方法如下: public ThreadPoolExecutor(int corePoolSize,   

JavaCallable實現多執行

一、Runnable和Callable< V >原始碼 先回顧一下Runnable和Callable< V >原始碼吧; //Runnable 原始碼 @FunctionalInterface public interface R

Java兩種多執行實現方式的區別

在程式開發中用到多執行緒,正統的方法是使用Runnable介面,相比繼承Thread類,Runnable介面有以下兩點好處: 1、避免單繼承機制的侷限,一個類可以實現多個介面 2、適用於資源的共享 下面以買票程式為例,分析繼承Thread類和實現Runnable介面的不同;

JAVA執行入門(二):JAVA如何寫多執行

第一種方式:繼承Thread 步驟: 1.建立執行緒類,繼承自Thread + 重寫run,run中寫執行緒體,執行緒體就是mian()函式裡面的寫法 2.使用執行緒: 2.1 建立執行緒物件 2.2 執行緒物件.start() 步驟展示: 1. public

關於java怎麼終止一個執行執行

其實現在要對一個迴圈執行的執行緒關閉,對迴圈執行體設定執行標誌是常見的方法。另外一種方法是使用interrupt方法中斷執行緒方式關閉執行緒。 使用interrupt方法中斷執行緒來退出執行緒 sleep wait io阻塞的情況下,對於這種執行緒退出的

Java的Socket.、執行和HaspMap的使用

Java中的Socket.、執行緒和HaspMap的使用 程式的功能:實現多人聊天 關鍵技術點說明:伺服器將每個客戶端的執行緒儲存在hashmap中,這樣就能實現資料正確轉發到哪個視窗。客戶端這邊將連線伺服器的執行緒也儲存起來,同時還要儲存執行緒對應的聊天介面,這樣通過讀

java 如何避免多執行安全

1.建立不可變物件 2. 執行緒封閉:把一個可變物件封裝到一個執行緒內部,或者使用ThreadLocal 3.使用volatile變數 volatile變數記憶體語義 1. 當對一個volatile變數進行寫操作的時候,JMM會把該執行緒對應的

c#Invoke使用方法(執行間操作無效: 從不是建立控制元件的執行訪問它。那麼建立它的執行是哪個執行?)

CSDN線下沙龍開發者與企業雲通訊服務選型CSDN線下沙龍開發者與企業雲通訊服務選型 匕敵都s68AG賞臥7H7攪第恐蛹爻逞 《 http://pregnant.baidu.com/article/cb559e95710bac242ace33686de6d5eb 》 臨磷

Java執行面試題(01) Java如何檢查一個執行是否擁特定物件的鎖

本文為本博主翻譯,未經允許,嚴禁轉載 簡介 考慮一個場景,在執行時你必須確認一個Java執行緒是否持有特定物件的鎖,例如,確認NewsReader執行緒是否持有NewsPaper物件的鎖?如果這個問題出現在任何核心的Java面試中,那麼我會自動假設可能有至少兩個答案,一個是

關於Java的程序和執行的理解

程式:一段靜態的程式碼,一組指令的有序集合,它本身沒有任何執行的含義,它只是一個靜態的實體,是應用軟體執行的藍本。程序:是程式的一次動態執行,它對應著從程式碼載入,執行至執行完畢的一個完整的過程,是一個動態的實體,它有自己的生命         週期。它因建立而產生,因排程而執行,因等待資源或事件而被處於等待

Java Web併發訪問的執行安全問題

Java Web併發訪問的執行緒安全問題 2018年05月12日 02:02:52 菜鳥級的IT之路 閱讀數:68更多 個人分類: JAVA~JavaWeb 一、Servlet的執行緒安全問題 Java web伺服器下,每個Servlet只有一個例項(即

Java併發程式設計(3)-構造執行安全類的模式

文章目錄 一、例項限制模式 1.1、 限制變數確保執行緒安全 1.2、分析ArrayList的執行緒安全性 1.3、總結 二、委託執行緒安全模式 2.