如果我使用fopen()調用在多線程中打開同一個文件,並將數據寫入文件。我應該使用互斥鎖來確保數據不會混亂嗎?Fopen()是Linux中的一個線程安全函數嗎?
6
A
回答
11
如果兩個線程都打開與fopen()
相同的文件,它們將分別擁有獨立的文件流(FILE *
),由獨立文件描述符引用相同的文件。您可以獨立寫入兩個文件流,但文件的最終結果將取決於線程寫入的位置以及刷新文件流的時間。除非您控制每個線程寫入的位置,否則結果是不可預測的。最簡單的事情是確保兩個線程使用相同的文件流,但您可能仍然需要在線程之間進行協調。需要注意的是POSIX要求C函數給文件流協作式接入 - 看看flockfile()
其強加了
所有功能引用
(FILE *)
對象,除了那些在_unlocked
結尾的名稱的要求,應表現爲,如果他們使用flockfile()
和funlockfile()
內部獲得這些(FILE *)對象的所有權。
如果您在兩個線程中都以追加模式打開文件,那麼每次寫入都將安全地放在文件末尾,但您仍然需要擔心在緩衝區填充之前刷新數據。
1
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;
}
相關問題
- 1. python函數是線程安全嗎? (特別是這個?)
- 2. linux內核的list.h線程安全嗎?
- 3. Linux中gettimeofday函數線程是否安全?
- 4. java:是hashmap.put(key,function())中線程安全的函數嗎?
- 5. 寫這個是線程安全的嗎?
- 6. 這個servlet是線程安全的嗎?
- 7. 是java.sql.Connection線程安全嗎?
- 8. 是CreateChildContainer()線程安全嗎?
- 9. 是Thread.getStackTrace()線程安全嗎?
- 10. 是DocumentBuilder.parse()線程安全嗎?
- 11. 是javax.sql.DataSource線程安全嗎?
- 12. 是TcpClient.Available線程安全嗎?
- 13. 是sqlite.swift線程安全嗎?
- 14. 是winsock2線程安全嗎?
- 15. 是unique_ptr線程安全嗎?
- 16. 是SplittableRandom.split()線程安全嗎?
- 17. 線程安全(是嗎?)
- 18. 是IP2Location線程安全嗎?
- 19. 是System.DirectoryServices.AccountManagement.GroupPrincipal線程安全嗎?
- 20. 是Microsoft.Practices.EnterpriseLibrary.Data.Database.SetParameterValue線程安全嗎?
- 21. 是java.util.UUID線程安全嗎?
- 22. 是enumerateUsingBlock:線程安全嗎?
- 23. 是java.util.concurrent.Future線程安全嗎?
- 24. 是DatagramSocket.send線程安全嗎?
- 25. 是長線程安全嗎?
- 26. 是SpelExpression線程安全嗎?
- 27. 是UImage.AsPNG()線程安全嗎?
- 28. 是ArrayDescriptor線程安全嗎?
- 29. 從函數返回一個QString - 線程安全嗎?
- 30. 是否是setlocale線程安全函數?
問題不在於與fopen()函數,但你怎麼寫文件。你需要做一些事情(一個互斥體就是一個例子)來控制寫入。 –
「記錄鎖定」也是一種選擇。它使您能夠鎖定文件的不同範圍。不同的線程可以同時寫入文件的不同部分。 –