线程同步

翻译自Qt帮助文档:Synchronizing Threads

多线程允许并行运行,有时候线程必须停下来等待其他的线程。例如,如果两个线程尝试同时往一个变量中写值,结果是未知的。强制线程等待另一个线程的规则叫互斥(mutal exclusion)。这种个普通的技术用来保护例如数据这样的共享资源。

对于同步线程,Qt提供了低级的基元和高级机制。


低级同步基元

QMutex 是强制互斥的基类。为了访问一个共享资源,一个线程锁住一个mutex。当mutex已经被锁住时,如果第二个线程尝试锁住它,那么第二个线程将会进入睡眠状态,直到第一个线程完成任务并解锁mutex。

除了区别对待read 和 write操作,QReadWriteLock 和QMutex其实是类似的。一段数据没被写入时,多线程同步读取数据是安全的。一个QMutex 强制多个读者按顺序读取共享数据,但是一个QReadWriteLock 允许同时读操作,从而提高并行性。

QSemaphore 是 QMutex 的泛化,它保护一定数量的相同资源。相反的,QMutex只保护一个资源。

QWaitCondition 不是通过强制互斥而是通过提供一个condition值达到同步线程的。当其他的基元让线程等待直到资源被解锁,QWaitCondition 会让线程等待直到满足一个特定的条件时。为了让等待的线程继续,调用 wakeOne() 来唤醒一个随机选择的线程或者调用 wakeAll() 来同时唤醒他们。

注意:这些同步类依赖于对合理的对齐的指针的使用。例如,你可以使用MSVC类包。

这些同步类可以用来让一个线程变的安全的。然而,这样做会导致性能有所下降,这是为什么大多数Qt方法并不是线程安全的原因。


风险

如果一个线程锁着一个资源但没有解锁,应用程序可能会阻塞,因为对于其他的线程这个资源将会永远不可用。这种情况完全有可能会发生,例如,如果一个被抛出来的异常,它强制要求当前函数返回,但未释放它的锁。

另一个相似的情形就是死锁(deadlock)。例如,假如线程A等待线程B去解锁一个资源。如果线程B同样在等待线程A去解锁一个不同的资源,那么这两个线程将会永远在等待,因此应用程序将会阻塞。


方便的类

QMutexLocker,QReadLocker 和 QWriteLocker 就是方便的类,它们可以让我们很方拜年的使用 QMutex 和 QReadWriteLock 类。当它们被创建的时候,它们就锁住一个资源,当它们被销毁时自动解锁资源。它们被设计用来简化那些使用了QMutex 和 QReadWriteLock 的代码,从而可以减少资源被永久锁住的几率。


高级事件队列

Qt的事件系统对线程间的交互非常有用。每个线程可以有自己的事件循环。为了调用其他线程的一个槽(或者任何可调用的方法),将那个调用放在目标线程的事件循环中。这让目标线程在槽开始运行前完成它自己当前的任务,期间原始线程继续并行运行。

为了将一个调用放在事件循环中,做一个队列话的信号-槽连接。当信号被发送时,它的实参将会被事件系统记录下来。接收信号的线程将会运行对应的槽。另外,不是用信号时调用QMetaObject::invokeMethod()  可以获取相同的效果。在这两种情况下,必须使用一个队列话的连接(queued connection),因为直接连接(direct connection)会绕过时间系统,并在当前线程中立即运行方法。

当为线程同步使用事件系统时,发生死锁是没有风险的,不像使用低级基元。然而,事件系统不会强制互斥。如果调用的方法访问共享的数据,它们必须使用低级基元来保护操作。

已经说过,伴随着隐式共享数据结构,Qt的事件系统提供了一个可替代传统线程锁定的方法。如果只使用信号和槽,并且两个线程间并没有共享的数据,多线程程序在没有低级基元的情况下完全可以做到。


注释:queued connection:当控制返回到接受者线程的事件循环中时,槽才会被调用。此时槽是在接收者的线程中执行的。

direct connection:当发送信号时,槽被立即执行,并且槽是在发送信号的线程中执行的。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值