线程和并行编程之线程同步(四)

线程的目的是为了并行的执行代码,有时线程需要互相等待。例如,如果两个线程同时写一个变量,执行结果是未定义的。因此对共享资源的需要进行“同步”处理。Qt提供了低级别的、高级别的机制处理线程同步。

低级别的线程同步

  • QMutex互斥量:为了访问共享资源,线程会锁定互斥量。其他的线程必须等该线程释放互斥量时,才可访问共享资源。
  • QReadWriteLock读写锁:区分对共享数据的“读”和“写”。多个线程可以同时读取共享数据,但是只有一个线程写共享数据。
  • QSemaphore信号量:保护若干数量的共享资源。常用于生产消费者的循环队列。
  • QWaitCondition等待条件:使信号处于等待状态,直到特定的条件被触发。可通过wakeOne()/wakeAll()唤醒其他线程。

上述同步类可以保证函数的线程安全。但是为了保证函数线程安全,会有性能的损耗,这也是为什么Qt部分函数不是线程安全的原因。

潜在风险

如果一个线程对资源加锁,但是没有释放锁,这个程序就有可能被冻结(因为该资源对于其他线程而言就是不能处理的)。例如:在函数内部抛出了异常并退出,但是在退出前并没有释放锁。

另外的场景就是死锁。例如:线程A等待线程B释放资源,但是线程B也在等待线程A释放资源,因此线程互相等待中(发生死锁)。

便利类

为了避免上述潜在风险第一种场景,Qt提供了Locker便利类:在构造函数中对资源加锁(调用lock),在析构函数中对资源释放锁(调用unLock)。

  • QMutex-QMutexLocker
  • QReadWriteLock-QReadLocker/QWriterLocker

高级别的线程同步

Qt的事件系统在线程通信中非常有用。每个线程都有独自的线程循环,为了在另外一个线程中调用槽函数,调用时机应该在目标线程的事件循环中。为了在事件循环中放置调用时机,应采用队列的信号槽连接方式。当发送信号时,它的参数会被记录到事件系统中,信号接收者所在的线程会执行槽函数。

不像使用低级别的线程同步原语,使用事件系统处理线程同步,不会有死锁的风险。但是,事件系统不强制处理互斥,如果调用方访问了共享资源,仍然需要使用低级别的线程同步原语保护共享资源。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值