无法设置条件变量
Not able to set conditional Variable
在下面的代码中,我在函数 waitingForWork()
中等待条件变量,但从未调用 doTheCleanUp()
。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool stop=false;
void stopTheWait()
{
sleep(5);
printf("stopping the wait.. \n\n");
std::lock_guard<std::mutex> lck(mtx);
stop = true;
cv.notify_all();
}
void doTheCleanUp()/* is never called*/ {
printf("clean up... \n\n");
}
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, []{ return stop;});
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}
int main()
{
printf("in main... \n");
std::unique_lock<std::mutex> lck(mtx);
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}
main()
正在锁定 std::mutex
,然后在同一个线程中调用 waitingForWork()
,它会再次尝试锁定 std::mutex
。 This is undefined behavior:
If lock
is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error
with error condition resource_deadlock_would_occur
instead of deadlocking.
没有充分理由main()
获得那个初始锁,摆脱它:
int main()
{
printf("in main... \n");
//std::unique_lock<std::mutex> lck(mtx); // <-- HERE
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}
注意,一般情况下,如果必须在同一个线程中多次锁定一个互斥锁,则需要使用std::recursive_mutex
代替:
A calling thread owns a recursive_mutex
for a period of time that starts when it successfully calls either lock
or try_lock
. During this period, the thread may make additional calls to lock
or try_lock
. The period of ownership ends when the thread makes a matching number of calls to unlock
.
另请注意,您需要在 t1
超出范围并被销毁之前调用 t1.join()
或 t1.detach()
,否则其 destructor 将中止调用进程:
If *this
has an associated thread (joinable() == true
), std::terminate()
is called.
你这里有一个错误:
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx); // This lock is bad.
// you already locked the
// mutex in main.
//
// locking it again is UB
cv.wait(lck, []{ return stop;}); // Once you enter wait()
// lock will be released
// until you are notified.
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}
在下面的代码中,我在函数 waitingForWork()
中等待条件变量,但从未调用 doTheCleanUp()
。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool stop=false;
void stopTheWait()
{
sleep(5);
printf("stopping the wait.. \n\n");
std::lock_guard<std::mutex> lck(mtx);
stop = true;
cv.notify_all();
}
void doTheCleanUp()/* is never called*/ {
printf("clean up... \n\n");
}
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, []{ return stop;});
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}
int main()
{
printf("in main... \n");
std::unique_lock<std::mutex> lck(mtx);
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}
main()
正在锁定 std::mutex
,然后在同一个线程中调用 waitingForWork()
,它会再次尝试锁定 std::mutex
。 This is undefined behavior:
If
lock
is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw astd::system_error
with error conditionresource_deadlock_would_occur
instead of deadlocking.
没有充分理由main()
获得那个初始锁,摆脱它:
int main()
{
printf("in main... \n");
//std::unique_lock<std::mutex> lck(mtx); // <-- HERE
std::thread t1(stopTheWait);
waitingForWork();
printf("exiting main...\n");
sleep(1);
return 0;
}
注意,一般情况下,如果必须在同一个线程中多次锁定一个互斥锁,则需要使用std::recursive_mutex
代替:
A calling thread owns a
recursive_mutex
for a period of time that starts when it successfully calls eitherlock
ortry_lock
. During this period, the thread may make additional calls tolock
ortry_lock
. The period of ownership ends when the thread makes a matching number of calls tounlock
.
另请注意,您需要在 t1
超出范围并被销毁之前调用 t1.join()
或 t1.detach()
,否则其 destructor 将中止调用进程:
If
*this
has an associated thread (joinable() == true
),std::terminate()
is called.
你这里有一个错误:
void waitingForWork(){
printf("wait for ever... \n\n");
std::unique_lock<std::mutex> lck(mtx); // This lock is bad.
// you already locked the
// mutex in main.
//
// locking it again is UB
cv.wait(lck, []{ return stop;}); // Once you enter wait()
// lock will be released
// until you are notified.
doTheCleanUp();
printf("clean Up Done, now end wait... \n\n");
}