gpt4 book ai didi

C++ 带定时器的多线程编程

转载 作者:搜寻专家 更新时间:2023-10-31 00:10:52 25 4
gpt4 key购买 nike

我是多线程编程的新手,所以这个问题可能看起来有点傻,但我真的需要解决这个问题,这样我才能将它应用到我的项目中(这要复杂得多)。以下是我的代码,我试图让 2 个线程(父线程和子线程)在执行时更新同一个共享计时器,并在计时器达到特定限制时停止。但是当我编译并执行下面这段代码时,有两种不同的结果: 1. child 打印“done by child at 200000”但是程序没有退出; 2. child打印“done by child at 200000”退出后,parent继续执行,打印几十行“parent doing work”和“parent at 190000”,然后打印“done by parent at 200000”和程序正确退出。我想要的行为是对于更新计时器、达到限制并退出的任何线程,另一个线程也应该停止执行并退出。我想我可能在这里遗漏了一些微不足道的东西,但我已经尝试过以多种方式更改代码,但我尝试的任何方法似乎都不起作用。任何帮助将不胜感激:)

#include <iostream>
#include <unistd.h>
#include <mutex>
#include <time.h>

using namespace std;

mutex mtx;

int main () {
int rc;
volatile int done = 0;
clock_t start = clock();
volatile clock_t now;

rc = fork();
if (rc == 0) { //child
while (true) {
cout << "child doing work" << endl;
mtx.lock();
now = clock() - start;
if (done) {
mtx.unlock();
break;
}
if (now >= 200000 && !done) {
done = 1;
cout << "done by child at " << now << endl;
mtx.unlock();
break;
}
cout << "child at " << now << endl;
mtx.unlock();
}
_exit(0);
}
else { // parent
while (true) {
cout << "parent doing work" << endl;
mtx.lock();
now = clock() - start;
if (done) {
mtx.unlock();
break;
}
if (now >= 200000 && !done) {
done = 1;
cout << "done by parent at " << now << endl;
mtx.unlock();
break;
}
cout << "parent at " << now << endl;
mtx.unlock();
}
}
return 0;
}

最佳答案

多进程

您的代码是多进程而非多线程: fork() 将通过复制调用进程来创建一个新的单独进程。

结果:在复制的那一刻,所有变量在两个进程中都包含相同的值。但是每个进程都有自己的拷贝,因此在父进程中修改的变量不会在子进程的地址空间中更新,反之亦然。

如果你想在进程之间共享变量,你应该看看this SO question

多线程

对于真正的多线程,你应该使用std::thread .忘记 volatile,因为它不是线程安全的。使用 <atomic> 相反,如本 awesome video 中所述.

这里是第一次尝试:

#include <iostream>
#include <mutex>
#include <thread>
#include <atomic>
#include <time.h>

using namespace std;

void child (atomic<int>& done, atomic<clock_t>& now, clock_t start)
{
while (!done) {
cout << "child doing work" << endl;
now = clock() - start;
if (now >= 2000 && !done) {
done = 1;
cout << "done by child at " << now << endl;
}
cout << "child at " << now << endl;
this_thread::yield();
}
}

void parent (atomic<int>& done, atomic<clock_t>& now, clock_t start)
{
while (!done) {
cout << "parent doing work" << endl;
now = clock() - start;
if (now >= 2000 && !done) {
done = 1;
cout << "done by parent at " << now << endl;
}
cout << "parent at " << now << endl;
this_thread::yield();
}
}

int main () {
atomic<int> done{0};
clock_t start = clock();
atomic<clock_t> now;

thread t(child, std::ref(done), std::ref(now), start); // attention, without ref, you get clones
parent (done, now, start);
t.join();

return 0;
}

请注意,您不需要使用互斥锁来保护原子访问,如果您想这样做, lock_guard 将被推荐替代。

这个例子当然是相当薄弱的,因为如果你在 if 条件下测试一个原子变量,它的值在进入 if block 时可能已经改变了。这不会导致您的逻辑出现问题,其中“完成”意味着“完成”。但如果你需要更谨慎的方法,
compare_exchange_weak() compare_exchange_strong() 可以帮助进一步。

关于C++ 带定时器的多线程编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36070677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com