这是启动和停止线程的安全方法吗?

3

假设我有一个名为 foo 的类,它在一个线程中执行一些任务。我想随时启动和停止这个任务。我的代码如下:

class foo
{

public:
    foo() {};
    ~foo() {};

    void start_thread() {
        thread_active = true;
        the_thread = std::thread(&foo::execute, this);
    }
    void stop_thread() {
        thread_active = false;
        the_thread.join();
    }

private:
    void execute() {
        while (thread_active)
            std::cout << "executing...\n";
    }

    std::thread the_thread;
    bool thread_active;
};

我这样调用它:

int main()
{
    foo bar;
    bar.start_thread();
    Sleep(1000);
    bar.stop_thread();
}

这样做安全吗?


2
我会将 thread_active 改为 std::atomic<bool> - Werner Henze
你需要使用互斥锁或是std::atomic来保护thread_active的并发,正如之前的评论建议的那样。 - turbopapero
例子在写操作之后使用内存栅仍将在 x86arm 上运行。 - Tarek Dakhran
1个回答

3

不,这并不是一种安全的方式。

原因是thread_active成员在多个线程中读取和写入时没有进行同步,应该将其声明为std::atomic_bool或使用其他形式的同步。


你能详细说明(例如提供一个例子)另一种同步形式吗? - JimBob
@JimBob:你可以使用std::mutex,在读取或写入之前实例化一个std::lock_guard以获取锁(虽然在这种情况下似乎有些过度保护)。 - 6502
请问能否解释一下:到底哪里不安全?线程中多运行一个while循环的风险大还是线程永远无法退出的风险大? - Vlad Feinstein
1
@VladFeinstein:如果你在一个线程中写入一个位置,并在另一个线程中读取相同的位置而没有同步,那么你就处于UB领域,任何事情都可能发生。编译器作者(甚至CPU设计者)可以自由地忽略处理这些行为,因为程序员不应该这样做。 - 6502
3
如果您在访问“thread_active”时不使用任何形式的同步,编译器可以自由地假设“thread_active”没有被其他线程修改。如果您将“std::cout << 'executing...\n';”替换为某个足够聪明的编译器(例如clang)可以推断出它既不修改“thread_active”,也不包含任何形式的同步的内容,那么您的线程将永远不会退出。 - Kit.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接