我已经编写了一个多线程练习示例程序。我在使用sleep_for(毫秒)函数的地方处于两难境地。 我正在尝试学习线程概念。因此,请将此视为我的实践,以了解三个线程如何同步。为了解它,我加入了睡眠。此外,我打算添加睡眠是为了在控制台上更清楚地看到输出。
请帮助我了解如何决定使用sleep_for的功能。
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
using namespace std;
using std::chrono::duration;
using std::chrono::system_clock;
void oneLine(mutex & mut, int nr)
{
lock_guard<mutex> lg(mut);
cout << "Thread # " << nr << endl;
// Should I call sleep_for here?
std::this_thread::sleep_for(chrono::milliseconds(25));
}
void callFun(mutex & mut, int nr)
{
while(true)
{
oneLine(mut, nr);
this_thread::yield();
// or here?
std::this_thread::sleep_for(chrono::milliseconds(250));
}
}
int main()
{
mutex thMutex;
thread t1(callFun, ref(thMutex), 1);
thread t2(callFun, ref(thMutex), 2);
thread t3(callFun, ref(thMutex), 3);
t1.join();
t2.join();
t3.join();
}
我在哪里可以在 oneLine()或 callFun()中调用 sleep_for 。 感谢。
答案 0 :(得分:3)
我认为你的例子非常适合学习多线程的基础知识。这一切都归结为您希望如何设计案例1或案例2的代码(请参阅下面代码中的标签)。
对于案例1,您在oneLine函数中调用sleep,以便在线程被生成之前和互斥锁超出范围之前调用它,从而防止下一个线程完成oneLine函数,直到它可以获取互斥锁上的锁定。如果您关心在下一个线程可以获取互斥锁之前有暂停,那么选择案例1.这是一个设计决定,由您自己决定代码中的应用程序。在情况2中,如果您希望另一个线程完成其oneLine调用而不必等待您为另一个线程指定的休眠期间放弃对互斥锁的锁定,则将其放在该函数之后。在案例2中,您只关心正在运行的同一个线程之间存在固定的暂停。
编辑:但是,在所有情况下,无法保证这些线程将以任何预定义的顺序访问互斥锁。对于案例1,案例2,我使用睡眠运行代码,并且没有睡眠,并且不保证顺序对于互斥锁是顺序的。
关于std :: this_thread ::来自http://en.cppreference.com/w/cpp/thread/yield
的收益此函数的确切行为取决于实现 特别是在使用的OS调度程序的机制和状态 系统的。例如,先进先出的实时调度程序 (Linux中的SCHED_FIFO)将挂起当前线程并将其打开 准备好的相同优先级线程队列的后面 run(如果没有其他线程具有相同的优先级,则yield 没有效果)。
因此,代码的行为也取决于操作系统调度程序。在我的情况下,当我运行它时,互斥锁从未按照确定的顺序。请参阅下面的截图,其中订单不是顺序的。
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <stdlib.h> //needed added here
using std::chrono::duration;
using std::chrono::system_clock;
void oneLine(std::mutex & mut, int nr)
{
std::lock_guard<std::mutex> lg(mut);
std::cout << "Thread # " << nr << std::endl;
// Case1
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
}
void callFun(std::mutex & mut, int nr)
{
while(true)
{
oneLine(mut, nr);
std::this_thread::yield();
// Case2
//std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
int main(int argc, char **argv)
{
std::mutex thMutex;
std::thread t1(callFun, ref(thMutex), 1);
std::thread t2(callFun, ref(thMutex), 2);
std::thread t3(callFun, ref(thMutex), 3);
t1.join(); // will never get here, because thread t1 in infinite loop
t2.join(); // will never get here, because thread t2 in infinite loop
t3.join(); // will never get here, because thread t3 in infinite loop
return(0); // will never get here because waiting for threads t1, t2, t3 to finish
}
答案 1 :(得分:2)
您的问题可归结为:您是否应该锁定互斥锁时调用sleep()
?或者使用互斥锁解锁?
这取决于你想要模拟的东西。你想模拟不经常发生的事情吗?然后sleep()
在受保护的块之外。如果要模拟需要很长时间的同步操作,则在受保护块内部sleep()
。
但请注意!
将互斥锁锁定超过几微秒的任何真实程序都是设计审核的一个重要标志。保持互斥锁长时间锁定的程序不太可能表现良好。
从不,......
以来,...
... sleep()
在任何真实程序中的互斥锁中。只是不,好吗?