2013-03-26 21 views
0

我創建連接到服務器,此外其他功能,登錄服務器聊到一個文件,這樣違規可被處罰後的客戶端應用。
不幸的是,它變得有必要在應用程序中有(至少)兩個線程:接收器循環和發送器循環 - 服務器需要定時準則。這意味着,我需要線程安全的解決方案來將數據記錄到文件中。
這是會發生什麼,如果線程發送日誌中(儘可能)同時信息:多線程FILESTREAM

logfile.txt: 
chat: Hello my name is Duke 
chat: Hell[WARNING]: Hacker detectedo my name is John 

你可以看到注入到另外一個句子。我不希望這種事情發生。我的std::cout輸出也是如此,但這並不重要。

問題:

  1. 我如何std::ofstream只能在同一時間登錄一個數據? (記住其他並插入後,不在中間)
  2. 如何檢查文件是否被其他線程關閉。 (或錯誤)

獎金的問題: 你能解決同樣的問題對於std::cout

+4

您將要寫入文件之前鎖定一個互斥體(或'的std :: cout') – 2013-03-26 22:10:56

+0

只是,我不希望阻止其他輸入,但要'std'做出自己的順序寫作。先拿一個輸入,然後輸入另一個輸入 – 2013-03-26 22:12:56

+0

您可以避免使用dauphic的最後一段進行阻止。 – 2013-03-26 22:13:37

回答

4

標準流沒有線程安全保證。要安全地完成要嘗試執行的操作的唯一方法是序列化對流的訪問。

最簡單的辦法是包涉及一個互斥體流的任何聲明。

{ 
    std::lock_guard<std::mutex> locked(gCoutMutex); 
    std::cout << "This is a message" << std::endl; 
} 

更正確的方法,特別是對於記錄器,是有一個帶有消息隊列的日誌記錄線程。當另一個線程想要記錄時,它只是向隊列發送一條消息,並且記錄線程將通過隊列並將所有內容寫入磁盤。

+0

我有一個類似的線程與發送到服務器的聊天消息的隊列 - 但「std :: vector」也是不安全的,所以有時應用程序崩潰。 – 2013-03-26 22:14:12

+0

+1 ...當然,訪問隊列時,您的*更正確的方法仍然需要互斥鎖。 – 2013-03-26 22:14:57

+0

標準庫在這裏沒有任何幫助。您需要編寫自己的線程安全隊列或使用另一個庫中的隊列。例如,boost :: asio :: io_service或者Boost.LockFree中的一個容器。我最喜歡的方法是'io_service'。 – 2013-03-26 22:15:33