您将锁定互斥体。不要在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;'应该就够了。 –