2012-11-15 104 views
1

所以我們假設我有以下代碼打開一個文件,逐行讀取內容,然後在其他地方使用每行功能,然後在完成倒帶文件時。多線程與文件

FILE *file = Open_File(); 
char line[max]; 
while (!EndofFile()) 
{ 
    int length = GetLength(line); 
    if (length > 0) 
    { 
     DoStuffToLine(line) 
    } 
} 
rewind(file); 

我想知道是否有一種方法來使用線程來添加併發。由於我只是閱讀文件而沒有寫入文件,所以我覺得我不必擔心競爭情況。但是我不確定如何處理while循環中的代碼,因爲如果一個線程在文件上循環,另一個線程同時在文件上循環,它們是否會導致對方跳過線條,使其他線程錯誤等?什麼是解決這個問題的好方法?

回答

2

如果您正在嘗試這樣做來提高讀取性能,您可能會感到失望,因爲這幾乎肯定會受到磁盤I/O限制。添加更多的線程無助於操作系統和磁盤控制器更快地獲取數據。

但是,如果您嘗試只是並行處理數據,那是另一回事。在這種情況下,我會將整個文件讀入內存緩衝區,然後讓您的線程並行處理它。這樣,您不必擔心線程安全性問題,因爲它會倒退文件指針或任何其他煩人的問題。

當然,您可能仍然需要爲多線程部分使用其他鎖定機制,具體取決於您在做什麼,但您不必擔心標準庫在您做什麼時要執行的操作開始訪問多個線程的文件。

+0

感謝您的幫助!在我的文件中,每行都是hashmap的關鍵字,所以當我調用「DoStuffToLine」時,我使用鍵來查找值。那麼這也會從線程中受益嗎?或者是從你提到的同一個I/O綁定的散列表中讀取? – user1782677

+0

@ user1782677好吧,首先,將整個文件首先讀入內存,而不是試圖檢索它的部分內容。在擔心其他類型的優化之前執行此操作。 – CookieOfFortune

+0

@ user1782677讀取散列映射將會受到內存I/O限制,所以不應該是從磁盤讀取時遇到的問題。但是,這可能還不能提供很多性能優勢,這取決於其他一百個細節。除非你的hashmap非常大,否則這可能沒有多大幫助。 – Telgin

0

我不確定這是最好的方法。但是,您可以閱讀該文件。然後將其存儲在兩個單獨的對象中,並讀取對象而不是文件。只要確保事後做清理。

1

併發增加了一些競爭狀態的問題:

的EndofFile()函數在循環的開始進行評估,可能總是會發生的,這個功能對於兩個線程返回true,那麼一個線程到達文件的結尾,另一個線程嘗試讀取文件。您永遠不知道線程何時可能正在執行;
2.對於GetLength函數也是一樣的:當線程有長度信息時,長度可能會改變,因爲另一個線程可能會讀取另一行;
3.即使您將其倒回,您正在順序讀取文件,但總是會發生IO指針的當前位置被其他某個線程更改的情況。

此外,正如Telgin指出的,讀取文件不受CPU綁定,但I/O限制,系統讀取文件也是如此。您無法提高性能,因爲您需要一些鎖定並鎖定保證線程安全只是引入開銷。