Qt线程:QMutex 和 QRecursiveMutex

QMutex

一、描述

QMutex是互斥量,用于给对象、数据结构、代码段加上索使它们成为互斥体,从而一次只有一个线程可以访问这些内容。

例如,假设有一个方法在两行上向用户打印一条消息:

 int number = 6;

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

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

如果连续调用这两个方法,会发生以下情况:

 // method1()
 number *= 5;        // number = 30
 number /= 4;        // number = 7

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

如果从两个线程同时调用这两个方法,则可能会产生以下序列:

 // 线程1调用method1()
 number *= 5;        // number = 30

 // 线程2调用method2(),线程1被操作系统置于睡眠状态
 number *= 3;        // number = 90
 number /= 2;        // number = 45

 //线程1接着执行
 number /= 4;        // number = 11,而不是10

如果添加一个互斥量,可以得到我们想要的结果:

 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();
 }

在任何给定时间只有一个线程可以修改数字并且结果是正确的。

当在线程中调用 lock() 时,其他尝试在同一位置调用 lock() 的线程将阻塞,直到获得锁的线程调用 unlock()。

QMutex 在非竞争情况下做了速度优化。如果互斥量没有争用,则非递归 QMutex 将不会分配内存。它的构建和销毁几乎没有任何开销,这意味着可以将许多互斥量作为其他类的一部分。


二、类型成员

1、enum QMutex::RecursionMode:递归模式

  • Recursive:递归模式。一个线程可以多次锁定同一个互斥量,并且在进行相应数量的 unlock() 调用之前互斥锁不会被解锁。(比NonRecursive更慢更耗内存)
  • NonRecursive:非递归模式,默认值。一个线程只能锁定一个互斥量一次。

三、成员函数

1、bool isRecursive() 

互斥量是否递归的。

2、void lock()

锁定互斥量。如果已有另一个线程锁定了互斥量,则此调用将阻塞,直到该线程将其解锁。

3、void unlock()

解锁互斥量。尝试在与锁定它的线程不同的线程中解锁互斥锁会导致错误。解锁未锁定的互斥量会导致未定义的行为。 

4、bool tryLock(int timeout = 0)

尝试锁定互斥量。成功则返回true(获得了锁)。如果已有另一个线程锁定了互斥量,此函数将最多等待timeout毫秒,之后如果互斥量还是被锁定状态则返回false。

传递一个负数相当于调用 lock(),即该函数将永远等待直到可以锁定互斥锁。

5、bool try_lock()

tryLock()功能一样,提供此函数是为了与标准库std::tryLock()兼容。

6、~QMutex()

销毁互斥量。销毁正在使用的互斥量会导致未定义行为。


QRecursiveMutex

QRecursiveMutex 类继承自 QMutex。它与 QMutex 的不同之处在于接受来自同一线程任意次数的 lock() 调用。QMutex 在这种情况下会死锁。

QRecursiveMutex 的构建和操作成本要高得多,因此请尽可能使用普通的 QMutex。

使用场景

当一个公共函数A调用另一个公共函数B,它们都需要锁定同一个互斥锁。在这种情况下可以使用QRecursiveMutex。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值