QT线程(二)---线程同步
2013-06-04 14:08
197 查看
转自:/article/9396444.html
线程互斥
多线程运行时,通常会访问同一个变量,同一个数据结构,或者同一段代码。因此,需要使用互斥技术来保护上述资源,确保多线程执行的正确性。
注:
我们通常说某个函数是线程安全的,也就是因为该函数实现加入了线程互斥保护。
4.1、QMutex
Mutex有两种模式,用户可以在构造函数参数中指定。
实例:
4.1、QMutexLocker
QMutexLocker实际上是对QMutex使用的一种简化。
例如以下场景:
当某段代码存在多个分支,在对QMutex加锁后,需要在不同的分支路径下都执行解锁操作,才能保证Mutex关联的资源能被其他线程继续访问,
否则就出现死锁。
QMutexLocker接收一个QMutex作为参数,当创建QMutexLocker对象时,就对关联的Mutex进行了Lock操作,直到该QMutexLocker对象被销毁,相关的QMutex才被Unlock。
实例:
直接使用QMutex:
使用QMutexLocker:
当然,使用QMutexLocker时,也需要注意QMutexLocker对象的生存周期,否则可能会出现锁时间过长,或者锁住的资源过多。
4.3、QReadLocker、QWriteLocker、QReadWriteLocker
还有一种场景,我们所保护的资源是具有读写权限的,多个线程可以同时读取某个资源,但是当存在写操作,写操作未完成时,就不允许其他线程对该资源进行读操作。
实例:
4.4、QSemaphore
和QMutex不同的是,QSemaphore一次可以对多个资源进行保护,
例如以下场景:
某工厂只有固定仓位,生产人员每天生产的产品数量不一,销售人员每天销售的产品数量也不一致。当生产人员生产P个产品时,就一次需要P个仓位,当销售人员销售C个产品时,就要求仓库中有足够多的产品才能销售。
如果剩余仓位没有P个时,该批次的产品都不存入,当当前已有的产品没有C个时,就不能销售C个以上的产品,直到新产品加入后方可销售。
这就是典型的生产者-消费者问题。
实例:
线程互斥
多线程运行时,通常会访问同一个变量,同一个数据结构,或者同一段代码。因此,需要使用互斥技术来保护上述资源,确保多线程执行的正确性。
注:
我们通常说某个函数是线程安全的,也就是因为该函数实现加入了线程互斥保护。
4.1、QMutex
Mutex有两种模式,用户可以在构造函数参数中指定。
实例:
QMutexmutex;
intnumber=6;
voidmethod1()
{
mutex.lock();
number*=5;
number/=4;
mutex.unlock();
}
voidmethod2()
{
mutex.lock();
number*=3;
number/=2;
mutex.unlock();
}
4.1、QMutexLocker
QMutex*mutex) | |
QMutex* | const |
void | |
void |
例如以下场景:
当某段代码存在多个分支,在对QMutex加锁后,需要在不同的分支路径下都执行解锁操作,才能保证Mutex关联的资源能被其他线程继续访问,
否则就出现死锁。
QMutexLocker接收一个QMutex作为参数,当创建QMutexLocker对象时,就对关联的Mutex进行了Lock操作,直到该QMutexLocker对象被销毁,相关的QMutex才被Unlock。
实例:
直接使用QMutex:
intcomplexFunction(intflag)
{
mutex.lock();
intretVal=0;
switch(flag){
case0:
case1:
mutex.unlock();
returnmoreComplexFunction(flag);
case2:
{
intstatus=anotherFunction();
if(status<0){
mutex.unlock();
return-2;
}
retVal=status+flag;
}
break;
default:
if(flag>10){
mutex.unlock();
return-1;
}
break;
}
mutex.unlock();
returnretVal;
}
使用QMutexLocker:
intcomplexFunction(intflag)
{
QMutexLockerlocker(&mutex);
intretVal=0;
switch(flag){
case0:
case1:
returnmoreComplexFunction(flag);
case2:
{
intstatus=anotherFunction();
if(status<0)
return-2;
retVal=status+flag;
}
break;
default:
if(flag>10)
return-1;
break;
}
returnretVal;
}
当然,使用QMutexLocker时,也需要注意QMutexLocker对象的生存周期,否则可能会出现锁时间过长,或者锁住的资源过多。
4.3、QReadLocker、QWriteLocker、QReadWriteLocker
还有一种场景,我们所保护的资源是具有读写权限的,多个线程可以同时读取某个资源,但是当存在写操作,写操作未完成时,就不允许其他线程对该资源进行读操作。
实例:
QReadWriteLocklock;
voidReaderThread::run()
{
...
lock.lockForRead();
read_file();
lock.unlock();
...
}
voidWriterThread::run()
{
...
lock.lockForWrite();
write_file();
lock.unlock();
...
}
4.4、QSemaphore
和QMutex不同的是,QSemaphore一次可以对多个资源进行保护,
例如以下场景:
某工厂只有固定仓位,生产人员每天生产的产品数量不一,销售人员每天销售的产品数量也不一致。当生产人员生产P个产品时,就一次需要P个仓位,当销售人员销售C个产品时,就要求仓库中有足够多的产品才能销售。
如果剩余仓位没有P个时,该批次的产品都不存入,当当前已有的产品没有C个时,就不能销售C个以上的产品,直到新产品加入后方可销售。
这就是典型的生产者-消费者问题。
实例:
QSemaphoresem(5);//sem.available()==5默认有5个产品
sem.acquire(3);//sem.available()==2销售3个产品,成功
sem.acquire(2);//sem.available()==0销售2个产品成功
sem.release(5);//sem.available()==5生产5个产品
sem.release(5);//sem.available()==10生产10个产品
sem.tryAcquire(1);//sem.available()==9,returnstrue消费1个产品,成功
sem.tryAcquire(250);//sem.available()==9,returnsfalse企图销售250个产品,失败,因为当前只剩下14个产品
相关文章推荐
- QT使用线程以及线程同步
- QT使用线程以及线程同步 .
- QT线程(二)---线程同步
- Qt修炼手册12_线程同步与线程等待条件
- QT线程(二)---线程同步
- qt 线程与ui线程同步
- qt 线程与ui线程同步
- qt 线程与ui线程同步
- QT线程(二)---线程同步
- QT线程(二)---线程同步
- [翻译]使用QThead进行线程开发&&线程同步
- 深入解析Java的线程同步以及线程间通信
- qt加入线程支持
- Java并发编程之线程管理(基本线程同步4)
- Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)
- Java并发编程之线程管理(基本线程同步5)
- C#中的线程(二) 线程同步基础
- 线程同步(使用了synchronized)和线程通讯(使用了wait,notify)
- QT事件循环与线程
- Java对多线程的支持(一) - Thread类、Runnable接口、Daemon线程、线程同步