您將鎖定互斥體。不要在999/1000的情況下手動鎖定互斥鎖。
在這種情況下,您可以使用std::unique_lock<std::mutex>
創建一個RAII鎖定器,以避免此問題。只需在示波器中創建它,並將鎖定區域結束於示波器的末端。
{
std::unique_lock<std::mutex> lock(mu);
stopServer = true;
}
在
main
和
{
std::unique_lock<std::mutex> lock(mu);
if (stopServer)
break;
}
在
serverFunction
。
現在在這種情況下,你的互斥量是毫無意義的。去掉它。將bool stopServer
替換爲std::atomic<bool> stopServer
,並從您的代碼中刪除對mutex
和mu
的所有引用。
可以安全地從不同線程讀取/寫入原子變量。
但是,您的代碼仍在等待。處理服務器處理消息的正確方法是守護消息隊列的條件變量。然後通過在消息隊列中對停止服務器消息(或標誌)進行排隊來停止它。
這會導致一個服務器線程無法喚醒,並且幾乎無時無刻地旋轉。相反,它阻塞條件變量(帶有一些虛假的喚醒,但很少見),並且只有在有新消息或被告知關閉時才真正醒來。
template<class T>
struct cross_thread_queue {
void push(T t) {
{
auto l = lock();
data.push_back(std::move(t));
}
cv.notify_one();
}
boost::optional<T> pop() {
auto l = lock();
cv.wait(l, [&]{ return halt || !data.empty(); });
if (halt) return {};
T r = data.front();
data.pop_front();
return std::move(r); // returning to optional<T>, so we'll explicitly `move` here.
}
void terminate() {
{
auto l = lock();
data.clear();
halt = true;
}
cv.notify_all();
}
private:
std::mutex m;
std::unique_lock<std::mutex> lock() {
return std::unique_lock<std::mutex>(m);
}
bool halt = false;
std::deque<T> data;
std::condition_variable cv;
};
我們使用boost::optional
爲pop
返回類型 - 如果隊列被暫停,彈出返回一個空可選。否則,它會阻塞,直到有數據。
您可以用任意類似的東西,甚至是第一個元素說明是否有任何東西要返回的東西,或std::unique_ptr<T>
或std::experimental::optional
或其他無數種選擇來替換它。
cross_thread_queue<int> queue;
bool serverFunction()
{
while (auto message = queue.pop()) {
// processing *message
std::cout << "Processing " << *message << std::endl;
}
std::cout << "Exiting func..." << std::endl;
return true;
}
int main()
{
std::thread serverThread(serverFunction);
// some stuff
queue.push(42);
system("pause");
queue.terminate();
serverThread.join();
}
live example。
std :: atomic stopServer;'應該就夠了。 –