2013-05-29 58 views
6

如果我使用fopen()調用在多線程中打開同一個文件,並將數據寫入文件。我應該使用互斥鎖來確保數據不會混亂嗎?Fopen()是Linux中的一個線程安全函數嗎?

+2

問題不在於與fopen()函數,但你怎麼寫文件。你需要做一些事情(一個互斥體就是一個例子)來控制寫入。 –

+0

「記錄鎖定」也是一種選擇。它使您能夠鎖定文件的不同範圍。不同的線程可以同時寫入文件的不同部分。 –

回答

11

如果兩個線程都打開與fopen()相同的文件,它們將分別擁有獨立的文件流(FILE *),由獨立文件描述符引用相同的文件。您可以獨立寫入兩個文件流,但文件的最終結果將取決於線程寫入的位置以及刷新文件流的時間。除非您控制每個線程寫入的位置,否則結果是不可預測的。最簡單的事情是確保兩個線程使用相同的文件流,但您可能仍然需要在線程之間進行協調。需要注意的是POSIX要求C函數給文件流協作式接入 - 看看flockfile()其強加了

所有功能引用(FILE *)對象,除了那些在_unlocked結尾的名稱的要求,應表現爲,如果他們使用flockfile()funlockfile()內部獲得這些(FILE *)對象的所有權。

如果您在兩個線程中都以追加模式打開文件,那麼每次寫入都將安全地放在文件末尾,但您仍然需要擔心在緩衝區填充之前刷新數據。

+0

我不確定我是否理解,如果我同時訪問(讀/寫)* differen *文件,我是否應該預料到任何問題? – ransh

+0

@ransh:如果兩個文件流在不同的文件打開,就不會有問題。如果它們在同一個文件中打開,則會出現問題。 –

+0

感謝澄清。 – ransh

1

據我所知,你應該使用mutexes

我還沒有嘗試,這是C,但在Java如果你在一個以上的thread打開file,既threads可以寫在它和file真的搞砸了。

所以我認爲C的情況將相當於Java

+8

猜測不是很好的答案 – stdcall

+0

其實我是說你應該嘗試一下。運行兩個線程,你會看到如何搞砸文件。 我在猜測什麼? –

+3

「所以我認爲C中的情況將等同於Java。」 - 這可以很容易地寫成評論,而不是答案。 – stdcall

1

fopen() is reenterable,並且您可以擁有儘可能多的描述符指向同一個文件。

作爲使用多個描述符從文件讀取/寫入的結果,您所得到的不是線程安全問題,而是併發文件訪問,在大多數情況下(除了文件是隻讀的時候)將無法正常工作。

1

下面是一個線程安全的打開文件寫你可以打開多個文件,它只是順序寫入文件。 我認爲下面的代碼可以用時間同步來依然優化,飛出未使用的文件,以保持高速緩存

任何建議,歡迎

class OpenFile 
{ 
    string fileName; 
    static map<string, unique_ptr<mutex>> fmap; 
    bool flag; 
public : 
    OpenFile(string file) : fileName(file) { 
     try { 
      if(checkFile(file)) 
      { 
       flag = false; 
       fmap.emplace(file, make_unique<mutex>()); 
      } 
      else 
      { 
       flag = true; 
      } 
     } 
     catch(string str) 
     { 
      cout << str << endl; 
     } 
    } 
    void writeToFile(const string& str) const 
    { 
     if (flag) 
     { 
      lock_guard<mutex> lck(*fmap.find(fileName)->second); 
      ofstream ofile(fileName, ios::app); 
      ofile << "Writing to the file " << str << endl; 
      ofile.close(); 
     } 
     else 
     { 
      ofstream ofile(fileName, ios::app); 
      ofile << "Writing to the file " << str << endl; 
      ofile.close(); 
     } 
    } 
    string ReadFile() const 
    { 
     string line; 
     if (flag) 
     { 
      lock_guard<mutex> lck(*fmap.find(fileName)->second); 
      ifstream ifile(fileName, ios::in); 
      getline(ifile, line); 
      ifile.close(); 
     } 
     else 
     { 
      ifstream ifile(fileName, ios::in); 
      getline(ifile, line); 
      ifile.close(); 
     } 
     return line; 
    } 
    OpenFile() = delete; 
    OpenFile& operator=(const OpenFile& o) = delete; 
    static bool checkFile(string& fname); 
}; 


bool OpenFile::checkFile(string& fname) 
{ 
    if (fmap.find(fname)==fmap.end()) 
    { 
     return true; 
    } 
    else 
     return false; 
} 
相關問題