关于Qt中的QMutex——关于lock与unlock

2021-10-15 16:37:22 浏览数 (1)

大概说一下用法,例子:

代码语言:javascript复制
QMutex mutex;
int number = 6;

void method1()
{
    mutex.lock();
    number *= 5;
    number /= 4;
    mutex.unlock();
}

void method2()
{
    mutex.lock();
    number *= 3;
    number /= 2;
    mutex.unlock();
}

用法大概可以总结为这样:

代码语言:javascript复制
QMutex mutex;

void method() {
    mutex.lock();
    // 你要做的骚操作
    mutex.unlock()
}

作用:确保同一时间只有一个线程可以运行lockunlock之间的内容。

其实这就是一个互斥锁,经常用的地方是在访问资源并作出修改的时候。这时候我们不希望有别的线程来同时访问同一个资源,所以会给两个线程要访问资源的地方的代码加上互斥锁,这样只有一个线程访问完资源处理完并unlock后,另一个线程才可以继续执行。所以可以看到,QMutexlock其实是阻塞式的,如果不能够取得锁那么没有办法继续往下执行。如果想要弄成非阻塞式的,那么就要用tryLock,并设置超时时长。但是这个就不展开说了。

例如,同时访问一个全局变量number

代码语言:javascript复制
int number = 6;

void method1()
{
    number *= 5;
    number /= 4;
}

void method2()
{
    number *= 3;
    number /= 2;
}

method1method2分别是由两个线程运行,正常情况下,我们的执行顺序应该是这样的:

代码语言:javascript复制
// method1()
number *= 5;        // number is now 30
number /= 4;        // number is now 7

// method2()
number *= 3;        // number is now 21
number /= 2;        // number is now 10

调用顺序不影响结果。

如果不加上互斥锁,那么可能执行的顺序是:

代码语言:javascript复制
// Thread 1 calls method1()
number *= 5;        // number is now 30

// Thread 2 calls method2().
//
// Most likely Thread 1 has been put to sleep by the operating
// system to allow Thread 2 to run.
number *= 3;        // number is now 90
number /= 2;        // number is now 45

// Thread 1 finishes executing.
number /= 4;        // number is now 11, instead of 10

所以我们需要加上互斥锁,确保当前只有一个进程访问变量number(可以看作是资源,其实原理都差不多):

代码语言:javascript复制
QMutex mutex;
int number = 6;

void method1()
{
    mutex.lock();
    number *= 5;
    number /= 4;
    mutex.unlock();
}

void method2()
{
    mutex.lock();
    number *= 3;
    number /= 2;
    mutex.unlock();
}

这样就可以确保只有一个线程完成了任务之后并且释放掉互斥锁之后,另一个线程才开始运行,保证了线程的完整运行和正确结果。

此外,可以通过成员函数bool QMutex::locked ()来确定一个互斥量有没有被lock。如果已经被锁定了返回true,否则返回false

参考

QMutex Class QMutex使用详解

0 人点赞