2009-01-20 133 views
3

我有一些代碼,將會從兩個線程訪問:多線程代碼 - 力執行順序


class Timer{ 
public: 
    void Start(){ 
     start_ = clock_->GetCurrentTime(); 
     running_ = true; 
    } 

    void Read(){ 
     if(running_){ 
     time_duration remaining = clock_->GetCurrentTime() - start_; 
     Actions(remaining) 
     } 
    } 

private: 
    void Actions(time_duration remaining); 
    time start_; 
    bool running; 
}; 

我看着在各個庫提供一些其他的計時器,但沒有發現任何適合我的要求,因此我滾動自己的...

Start()方法從一個線程被調用(僅一次)。 Read()方法在另一個線程中被非常快速地調用,調用將在Start()被調用之前開始。

顯然,在設置running_標誌之前,初始化start_變量之前是,這非常重要。這可以通過添加一個互斥體來獲得,該互斥體在進入Start()方法時被抓住並且在Read()方法中檢查running_之前抓取...但似乎沒有必要。如果這裏的一切按順序執行,那就沒有問題了。在另一個線程處於Start()路由中的時候,Read()會發生,並且從時鐘獲取時間,例如... Read()發生的速度足夠快以至於它不是一個大不了。

反正,我一直在尋找一種方法來確保編譯器/處理器將在它們上面列出的順序執行

start_ = clock_->GetCurrentTime(); 
    running_ = true; 

指令。 (或者如果我忽略了別的東西)。

回答

1

爲什麼不擺脫「運行」標誌並使用「start」變量是否爲空作爲條件?你沒有指定一種語言,但是對於「開始」而言,某種揮發性標記也是一個好主意。這也假設「開始」可以被原子寫入。例如:

class Timer{ 
public: 
    void Start(){ 
    start_ = clock_->GetCurrentTime(); 
    } 
    void Read(){ 
    if(nullptr != start_){ 
    time_duration remaining = clock_->GetCurrentTime() - start_; 
    Actions(remaining)  
    } 
} 
private: 
    void Actions(time_duration remaining); 
    volatile time start_; 
}; 
+0

這不起作用,因爲start_不是一個小原子事物。 – teeks99 2009-01-20 21:55:21

0

我不確定我是否理解你的問題,但是我認爲你想阻止在Start方法尚未設置(或尚未完全執行)時執行Read操作?

如果是這樣的話,你不能通過使用AutoResetEvent或ManualResetEvent(取決於你想要的行爲)來解決你的問題。

在Read方法中,您可以指定在Auto/ManualResetEvent尚未設置時Read方法應該等待,並且在Start方法結束時可以設置Event。

3

您需要使start_和running_volatile,然後在Start()兩個分配之間引入一個內存屏障。

+0

我在想這些方面......但我正在尋找更多的細節。 所有編譯器是否支持volatile?你知道關於記憶障礙的任何好文檔嗎? – teeks99 2009-01-20 17:16:47

0

爲什麼不只是堅持一個

 
if (_running == false) Start(); 

在Read()方法。 並且保護啓動互斥或將其定義爲「關鍵」以確保其單線程。

+0

我不想在每次Read()被調用時運行......很多時候,在調用Read()時什麼都不應該發生。 – teeks99 2009-01-20 17:21:46