C++ 互斥是从不同的线程访问外部变量所必需的吗?
我正在用Qt/C++开发一个应用程序。在某些情况下,有两个线程:一个是UI线程,另一个是后台线程。我必须根据外部变量的值从后台线程执行一些操作,该变量的类型为C++ 互斥是从不同的线程访问外部变量所必需的吗?,c++,multithreading,qt,mutex,C++,Multithreading,Qt,Mutex,我正在用Qt/C++开发一个应用程序。在某些情况下,有两个线程:一个是UI线程,另一个是后台线程。我必须根据外部变量的值从后台线程执行一些操作,该变量的类型为bool。我通过单击UI上的按钮来设置此值 标题.cpp extern bool globalVar; //main ui thread on button click setVale(bool val){ globalVar = val; } while(1){ if(globalVar) //do some oper
bool
。我通过单击UI上的按钮来设置此值
标题.cpp
extern bool globalVar;
//main ui thread on button click
setVale(bool val){
globalVar = val;
}
while(1){
if(globalVar)
//do some operation
else
//do some other operation
}
main window.cpp
extern bool globalVar;
//main ui thread on button click
setVale(bool val){
globalVar = val;
}
while(1){
if(globalVar)
//do some operation
else
//do some other operation
}
backgroundThread.cpp
extern bool globalVar;
//main ui thread on button click
setVale(bool val){
globalVar = val;
}
while(1){
if(globalVar)
//do some operation
else
//do some other operation
}
在这里,只有当用户单击按钮时才会写入globalVar
,而读取是连续进行的
所以我的问题是:
globalVar
是否将具有除true
或false
以外的值因为它只是一个简单的布尔值,我认为互斥是多余的,所以你应该选择一个原子整数。原子将在单个CPU时钟中读取和写入,因此无需担心,而且它将是无锁的,如果可能,这总是更好的 如果是更复杂的东西,那么一定要使用互斥 它不会因此而崩溃,但您可能会导致数据损坏,这可能会使应用程序崩溃 系统不会为您管理这些内容,您可以手动操作,只需确保所有数据访问都通过互斥锁即可 编辑: 由于您多次指定了不需要复杂解决方案的情况,因此可以选择简单地使用互斥体而不是bool。没有必要使用互斥来保护bool,因为可以将互斥用作bool,是的,可以使用原子,但互斥已经做到了这一点(加上递归互斥的一些额外功能) 您的确切工作量是多少也很重要,因为您的示例在实践中没有多大意义。了解这些
操作是什么将很有帮助
因此,在您的ui线程中,您可以简单地val?mutex.lock():mutex.unlock()
,在辅助线程中,如果(mutex.tryLock())doStuff,则可以使用;mutex.unlock();其他的东西代码>。现在,如果次线程中的操作花费的时间太长,而您恰好更改了主线程中的锁,那么将阻塞主线程,直到次线程解锁。您可以在主线程中使用tryLock(timeout)
,具体取决于您的喜好,lock()
将阻塞直到成功,而tryLock(timeout)
将阻止阻塞,但锁可能会失败。另外,注意不要从锁定线程以外的线程解锁,也不要解锁已解锁的互斥锁
根据您实际执行的操作,异步事件驱动方法可能更合适。当(1)
时,您真的需要它吗?您执行这些操作的频率是多少?因为它只是一个简单的布尔值,我认为互斥是多余的,所以您应该选择原子整数。原子将在单个CPU时钟中读取和写入,因此无需担心,而且它将是无锁的,如果可能,这总是更好的
如果是更复杂的东西,那么一定要使用互斥
它不会因此而崩溃,但您可能会导致数据损坏,这可能会使应用程序崩溃
系统不会为您管理这些内容,您可以手动操作,只需确保所有数据访问都通过互斥锁即可
编辑:
由于您多次指定了不需要复杂解决方案的情况,因此可以选择简单地使用互斥体而不是bool。没有必要使用互斥来保护bool,因为可以将互斥用作bool,是的,可以使用原子,但互斥已经做到了这一点(加上递归互斥的一些额外功能)
您的确切工作量是多少也很重要,因为您的示例在实践中没有多大意义。了解这些操作是什么将很有帮助
因此,在您的ui线程中,您可以简单地val?mutex.lock():mutex.unlock()
,在辅助线程中,如果(mutex.tryLock())doStuff,则可以使用;mutex.unlock();其他的东西代码>。现在,如果次线程中的操作花费的时间太长,而您恰好更改了主线程中的锁,那么将阻塞主线程,直到次线程解锁。您可以在主线程中使用tryLock(timeout)
,具体取决于您的喜好,lock()
将阻塞直到成功,而tryLock(timeout)
将阻止阻塞,但锁可能会失败。另外,注意不要从锁定线程以外的线程解锁,也不要解锁已解锁的互斥锁
根据您实际执行的操作,异步事件驱动方法可能更合适。当(1)
时,您真的需要它吗?您多久执行一次这些操作?循环
while(1){
if(globalVar)
//do some operation
else
//do some other operation
}
是,非常浪费。因此,您最好使用一些经典的同步,当有事情要做时,这些同步将唤醒后台线程(大部分)。你应该考虑适应。
假设您从以下内容开始:
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool ready = false;
#包括
#包括
#包括
std::互斥m;
std::条件变量cv;
bool ready=false;
您的工作线程可以是这样的:
void worker_thread()
{
while(true)
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return ready;});
ready = false;
lk.unlock();
}
{
std::lock_guard<std::mutex> lk(m);
ready = true;
}
cv.notify_one();
void worker\u thread()
{
while(true)
{
//等待main()发送数据
std::唯一锁lk(m);
cv.wait(lk,[{return ready;});
就绪=错误;