gpt4 book ai didi

c++ - 使用循环使相同的线程在没有 sleep 的情况下一次又一次地获得相同的互斥锁

转载 作者:行者123 更新时间:2023-11-30 05:15:57 27 4
gpt4 key购买 nike

我想在两个线程中计算两个东西,每个线程都有一个无限循环。这两者互不依赖。

此外,我还希望终端上的一些输出也处于无限循环中(每次计算最后一个输出时重新开始,不需要中间的任何步骤)。因此,我希望全局变量的一些本地拷贝(第一次计算的两次连续迭代和第二次计算的一个值)都处于安全状态。

现在的问题是我必须在两个计算中添加一些 sleep 才能从 func1 获得一些输出。我检查了 CPU 使用率, sleep 肯定会降低它。我该如何解决这个问题?

另见测试评论:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>

int n(0);
long s(1234);
double t(56.78);

std::condition_variable cond;
std::mutex m1;
std::mutex m2;

void func1() {
while (true) {
// Not needed due to wait unlocking the mutex
//std::this_thread::sleep_for(std::chrono::nanoseconds(1));

std::unique_lock<std::mutex> lck1(m1);
cond.wait(lck1);
int n1(n);
long s1(s);
cond.wait(lck1);
int n2(n);
long s2(s);
lck1.unlock();

std::unique_lock<std::mutex> lck2(m2);
double ti(t);
lck2.unlock();

// calculate and print some output
std::this_thread::sleep_for(std::chrono::milliseconds((n1*n2)/2));
std::cout << n1 << ":" << s1 << ", " << n2 << ":" << s2 << ", " << ti << std::endl;
}
}

void func2() {
while (true) {
// Why do I need this to make func1 ever proceed (ok, really seldom and random func1 got the mutex) and
// how to work around this without sleep lowering time for computations?
std::this_thread::sleep_for(std::chrono::nanoseconds(1)); // comment out to test

std::unique_lock<std::mutex> lck1(m1);

n++;

// do some stuff taking some time with s
std::this_thread::sleep_for(std::chrono::milliseconds((n*n)/3));

cond.notify_all();
}
}

void func3() {
while (true) {
// Why do I need this to make func1 ever proceed (it got the mutex never ever) and
// how to work around this without sleep lowering time for computations?
std::this_thread::sleep_for(std::chrono::nanoseconds(1)); // comment out to test

std::unique_lock<std::mutex> lck2(m2);
// do something taking some time with t
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}

int main() {

std::thread t1(func1);
std::thread t2(func2);
std::thread t3(func3);

t1.join();
t2.join();
t3.join();

return 0;
}

最佳答案

首先,您必须假设条件变量 wait 调用实际上并不等待。一个有效的(尽管极端的)实现是 lk.unlock(); lk.lock();,有时由于“虚假唤醒”,它确实表现得像那样。您确实需要将条件与条件变量相关联,并在不满足条件时循环。

其次,如果您在持有互斥量锁的同时通知条件变量,则等待线程将从通知中唤醒,只会阻塞在互斥量上,因此通知线程可能会在等待线程获得互斥量之前重新获取互斥量一个机会。

因此最好在通知条件变量之前解锁互斥量。

lck1.unlock();
cond.notify_all();

这使等待线程有机会在通知线程重新获取锁之前立即获取互斥锁。

您可以在迭代之间添加 std::this_thread::yield() 调用,让其他线程有机会获取锁。然而,这并不理想——任何你必须明确地做一些事情来扰乱调度程序的代码都是重写的目标。

关于c++ - 使用循环使相同的线程在没有 sleep 的情况下一次又一次地获得相同的互斥锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42879362/

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