C++ 如何说std::线程停止?
我有两个问题 1) 我想启动一些带有无限循环的函数,使其像服务器一样工作,并在单独的线程中检查消息。但是,我希望在需要时从父线程关闭它。在这种情况下,我不知道如何C++ 如何说std::线程停止?,c++,multithreading,c++11,C++,Multithreading,C++11,我有两个问题 1) 我想启动一些带有无限循环的函数,使其像服务器一样工作,并在单独的线程中检查消息。但是,我希望在需要时从父线程关闭它。在这种情况下,我不知道如何std::future或std::condition\u variable。还是最好创建一些全局变量并从父线程将其更改为true/false。 2) 我想要这样的东西。为什么此示例在运行时崩溃? #include <iostream> #include <chrono> #include <thread&g
std::future
或std::condition\u variable
。还是最好创建一些全局变量并从父线程将其更改为true/false。2) 我想要这样的东西。为什么此示例在运行时崩溃?
#include <iostream>
#include <chrono>
#include <thread>
#include <future>
std::mutex mu;
bool stopServer = false;
bool serverFunction()
{
while (true)
{
// checking for messages...
// processing messages
std::this_thread::sleep_for(std::chrono::seconds(1));
mu.lock();
if (stopServer)
break;
mu.unlock();
}
std::cout << "Exiting func..." << std::endl;
return true;
}
int main()
{
std::thread serverThread(serverFunction);
// some stuff
system("pause");
mu.lock();
stopServer = true;
mu.unlock();
serverThread.join();
}
#包括
#包括
#包括
#包括
std::互斥mu;
boolstopserver=false;
boolserverfunction()
{
while(true)
{
//正在检查邮件。。。
//处理消息
std::this_thread::sleep_for(std::chrono::seconds(1));
mu.lock();
如果(停止服务器)
打破
mu.unlock();
}
标准::cout
为什么这个示例在运行时崩溃
当您离开线程的内部循环时,您会使互斥锁保持锁定状态,因此如果您再次使用该互斥锁,父线程可能会永远被阻塞
您应该使用std::unique_lock
或类似的方法来避免类似的问题
为什么这个示例在运行时崩溃
当您离开线程的内部循环时,您会使互斥锁保持锁定状态,因此如果您再次使用该互斥锁,父线程可能会永远被阻塞
您应该使用std::unique\u lock
或类似的方法来避免类似的问题。您将互斥锁留在锁定状态。在999/1000情况下,不要手动锁定互斥锁
在这种情况下,您可以使用std::unique_lock
创建一个RAII锁固定器来避免此问题。只需在作用域中创建它,并将锁区域结束在作用域的末尾
{
std::unique_lock<std::mutex> lock(mu);
stopServer = true;
}
在serverFunction
中
现在,在这种情况下,您的互斥是没有意义的。请删除它。将bool stopServer
替换为std::atomic 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;
};
.您保持互斥锁锁定。在999/1000情况下,不要手动锁定互斥锁
在这种情况下,您可以使用std::unique_lock
创建一个RAII锁固定器来避免此问题。只需在作用域中创建它,并将锁区域结束在作用域的末尾
{
std::unique_lock<std::mutex> lock(mu);
stopServer = true;
}
在serverFunction
中
现在,在这种情况下,您的互斥是没有意义的。请删除它。将bool stopServer
替换为std::atomic 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;
};
.Astd::atomic stopServer;
应该足够了。Astd::atomic stopServer;
应该足够了。我认为这种情况不会出现,因为互斥锁只在主服务器和“服务器”内部获得和释放一次-循环只有在主操作已经发生的情况下才会保留未发布状态。@banana36您的解决方案还可以,但是-正如一位评论者所指出的-您应该使用std::atomic变量。您使用的方法非常常见。@Skym0sh0-我们不知道崩溃的确切原因,但OP线程的实现可能会检测到这种情况(仍持有互斥锁时线程退出)然后抛出一个异常?它不会在我的电脑上崩溃,但我必须将暂停更改为睡眠5
@banana36-哦,如果条件很简单,你不需要互斥,那么单独使用std::atomic
就可以了。@FreddieChopin是的,你是对的。你的初始答案也很完美。那么你就永远安全了一切正常。我认为这种情况不会出现,因为互斥只有一次在主服务器和“服务器”内部获得和释放-循环只有在主操作已经发生的情况下才会保留未发布状态。@banana36您的解决方案还可以,但是-正如一位评论者所指出的-您应该使用std::atomic变量。您使用的方法非常常见。@Skym0sh0-我们不知道崩溃的确切原因,但OP线程的实现可能会检测到这种情况(仍持有互斥锁时线程退出)然后抛出一个异常?它不会在我的电脑上崩溃,但我必须将暂停更改为睡眠5
@banana36-哦,如果条件很简单,你不需要互斥,那么单独使用std::atomic
就可以了。@FreddieChopin是的,你是对的。你的初始答案也很完美。那么你就永远安全了一切都好。