2015-05-05 48 views
1

編輯
我通過在Shared結構中使用單個互斥變量而不是Unique中的多個互斥體來解決我的問題。如果有人明白爲什麼這個工作,而另一個不(可靠),我會很樂意接受答案。
編輯C++ 11線程池在windows上運行 - linux上的塊

我寫了一個簡單的線程池與c + + 11線程。在Windows上它的行爲像預期的那樣,但是在Linux上它會阻塞。我假設我編寫了錯誤的代碼,它只是在巧合的窗口上運行。

想法是創建一次池並且多次調用run(),它在所有可用的線程上運行一次程序,然後返回而不破壞線程。線程然後等待下一次運行,等等。

在windows上,每當我嘗試它時都會工作。然而,在Linux上,只有一個線程開始執行程序,之後沒有任何反應,所以run()永遠不會返回。

我已經包含了一個我的源代碼的略微縮減的版本,因爲我認爲這個東西可能夠小。如果有人有興趣看看我懷疑代碼段中間的loop()和wait_all()是最相關的部分。如果變量類型不能從名稱/上下文中清除,我還將該聲明作爲參考。

Pool::Pool(uint32_t num_threads) : num_threads_(num_threads), uniques_(num_threads), threads_(num_threads) { 
    shared_.end = false; 

    for (uint32_t i = 0; i < num_threads; ++i) { 
     uniques_[i].wake = false; 
     threads_[i] = std::thread(loop, std::ref(uniques_[i]), std::ref(shared_)); 
    } 
} 

void Pool::run(Program program) { 
    shared_.program = program; 
    wake_all(); 
    wait_all(); 
} 

void Pool::wake_all() { 
    for (size_t i = 0; i < uniques_.size(); ++i) { 
     uniques_[i].wake = true; 
    } 

    shared_.wake_signal.notify_all(); 
} 

void Pool::wait_all() { 
    for (size_t i = 0; i < num_threads_; ++i) { 
     std::unique_lock<std::mutex> locker(uniques_[i].lock); 
     uniques_[i].done_signal.wait(locker, [&]{return !uniques_[i].wake;}); 
    } 
} 

void Pool::loop(Unique& unique, Shared& shared) { 
    for (;;) { 
     std::unique_lock<std::mutex> locker(unique.lock); 
     shared.wake_signal.wait(locker, [&]{return unique.wake;}); 

     if (shared.end) { 
      break; 
     } 

     // Do stuff... On linux only a single thread gets here 
     shared.program(); 

     unique.wake = false; 
     locker.unlock(); 
     unique.done_signal.notify_all(); 
    } 
} 

// Declaration 
class Pool { 
public: 
    typedef std::function<void()> Program; 
    Pool(uint32_t num_threads); 
    void run(Program program); 
private: 
    void wake_all(); 
    void wait_all(); 

    struct Unique { 
     std::condition_variable done_signal; 
     std::mutex lock; 
     bool wake; 
    }; 

    struct Shared { 
     Program program; 
     std::condition_variable wake_signal; 
     bool end; 
    }; 

    uint32_t num_threads_; 
    Shared shared_; 
    std::vector<Unique> uniques_; 
    std::vector<std::thread> threads_; 

    static void loop(Unique& unique, Shared& shared); 
}; 
+0

你的謂詞倒退在'wait_all'中。你想等待喚醒爲真,而不是假。此外,'wake_all'函數修改共享狀態('喚醒'布爾值),而不需要保持保護該狀態的鎖。 –

+0

「共享」和「唯一」類型對我來說似乎沒有任何意義。 'Shared'在條件變量旁邊缺少一個互斥。你有沒有在死鎖狀態下調試你的代碼? – Yakk

+0

@DavidSchwartz:wait_all中的顛倒謂詞是故意的。這可能有點不清楚,但想法是在wake_all中等待wake == true,在wait_all中等待wake == false。變量爲「喚醒我」和「我完成了」雙打。至少這是該計劃。 –

回答

0

您違反了標準的要求進行調用wait

無效的等待(unique_lock &鎖);

需要:lock.owns_lock()爲真和lock.mutex()被調用線程鎖定,並且:

- 沒有其他線程正在等待這個condition_variable對象或

上 - 鎖.mutex()爲所有併發等待(通過wait或timed_wait)線程提供的每個鎖參數返回相同的值。

您可以同時等待線程的lock引用不同的mutex。因此,您不符合在condition_variable上撥打wait的先決條件。

我相信你可以使用condition_variable_any,它沒有這個要求。

相關問題