您的位置:首页 > 编程语言 > Qt开发

QT线程(二)---线程同步

2013-06-18 10:50 239 查看
线程互斥
      
多线程运行时,通常会访问同一个变量,同一个数据结构,或者同一段代码。因此,需要使用互斥技术来保护上述资源,确保多线程执行的正确性。
注:
我们通常说某个函数是线程安全的,也就是因为该函数实现加入了线程互斥保护。
 
 
      
4.1、QMutex
 
QMutex (
RecursionMode mode = NonRecursive )
 
~QMutex ()
void
lock ()
mutex加锁,如果当前其他线程已对该mutex加锁了,则该调用被阻塞直到其他线程释放该mutex。
bool
tryLock ()
mutex加锁,和lock不同的是,如果当前其他线程已对该mutex加锁了,则该调用会立即返回,而不被阻塞。
bool
tryLock (
int timeout )
同tryLock,和tryLock不同的是,如果当前其他线程已对该mutex加锁了,则该调用会等待一段时间,直到超时或者其他线程释放了mutex。
void
unlock ()
mutex解锁,释放被锁住的资源。
 
      
Mutex有两种模式,用户可以在构造函数参数中指定。
      

Constant
Value
Description
QMutex::Recursive
1
In this mode, a thread can lock the same mutex multiple times and the mutex won't
be unlocked until a corresponding number of unlock()
calls have been made.
该模式下,一个线程可以对mutex多次lock,直到相应次数的unlock,调用后,该mutex才真正被unlock。
QMutex::NonRecursive
0
In this mode, a thread may only lock a mutex once.
该模式下,mutex只能被lock一次。
 
 
实例:

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

}


 
      
4.1、QMutexLocker
 
 
QMutexLocker (
QMutex * mutex )
 
~QMutexLocker ()
QMutex *
mutex ()
const
void
relock ()
void
unlock ()
 
      
QMutexLocker实际上是对QMutex使用的一种简化。
例如以下场景:
             
当某段代码存在多个分支,在对QMutex加锁后,需要在不同的分支路径下都执行解锁操作,才能保证Mutex关联的资源能被其他线程继续访问,      
否则就出现死锁。
      
QMutexLocker接收一个QMutex作为参数,当创建QMutexLocker对象时,就对关联的Mutex进行了Lock操作,直到该QMutexLocker对象被销毁,相关的QMutex才被Unlock。
 
 
实例:
      
直接使用QMutex:

int complexFunction(int flag)

{

     mutex.lock();

 

     int retVal = 0;

 

     switch (flag){

     case 0:

     case 1:

         mutex.unlock();

         return moreComplexFunction(flag);

     case 2:

        {

             int status = anotherFunction();

             if (status < 0){

                 mutex.unlock();

                 return -2;

            }

             retVal = status + flag;

        }

         break;

     default:

         if (flag > 10){

             mutex.unlock();

             return -1;

        }

         break;

    }

 

     mutex.unlock();

     return retVal;

}


 
使用QMutexLocker:

int complexFunction(int flag)

{

     QMutexLocker locker(&mutex);

 

     int retVal = 0;

 

     switch (flag){

     case 0:

     case 1:

         return moreComplexFunction(flag);

     case 2:

        {

             int status = anotherFunction();

             if (status < 0)

                 return -2;

             retVal = status + flag;

        }

         break;

     default:

         if (flag > 10)

             return -1;

         break;

    }

 

     return retVal;

}


 
当然,使用QMutexLocker时,也需要注意QMutexLocker对象的生存周期,否则可能会出现锁时间过长,或者锁住的资源过多。
 
 
4.3、QReadLocker、QWriteLocker、QReadWriteLocker
      
还有一种场景,我们所保护的资源是具有读写权限的,多个线程可以同时读取某个资源,但是当存在写操作,写操作未完成时,就不允许其他线程对该资源进行读操作。
 
 
QReadWriteLock ()
 
QReadWriteLock (
RecursionMode recursionMode )
 
~QReadWriteLock ()
void
lockForRead ()
void
lockForWrite ()
bool
tryLockForRead ()
bool
tryLockForRead (
int timeout )
bool
tryLockForWrite ()
bool
tryLockForWrite (
int timeout )
void
unlock ()
 
 
 
QReadLocker (
QReadWriteLock * lock )
 
~QReadLocker ()
QReadWriteLock *
readWriteLock ()
const
void
relock ()
void
unlock ()
 
 
QWriteLocker (
QReadWriteLock * lock )
 
~QWriteLocker ()
QReadWriteLock *
readWriteLock ()
const
void
relock ()
void
unlock ()
 
实例:

QReadWriteLock lock;

 

void ReaderThread::run()

{

     ...

     lock.lockForRead();

     read_file();

     lock.unlock();

     ...

}

 

void WriterThread::run()

{

     ...

     lock.lockForWrite();

     write_file();

     lock.unlock();

     ...

}


 
4.4、QSemaphore
      
和QMutex不同的是,QSemaphore一次可以对多个资源进行保护,
例如以下场景:
      
某工厂只有固定仓位,生产人员每天生产的产品数量不一,销售人员每天销售的产品数量也不一致。当生产人员生产P个产品时,就一次需要P个仓位,当销售人员销售C个产品时,就要求仓库中有足够多的产品才能销售。
如果剩余仓位没有P个时,该批次的产品都不存入,当当前已有的产品没有C个时,就不能销售C个以上的产品,直到新产品加入后方可销售。
      
这就是典型的生产者-消费者问题。
 
 
QSemaphore (
int n = 0 )
 
~QSemaphore ()
void
acquire (
int n = 1 )
int
available ()
const
void
release (
int n = 1 )
bool
tryAcquire (
int n = 1 )
bool
tryAcquire (
int n, int timeout )
 
实例:

QSemaphore sem(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, returns true 消费1个产品,成功

sem.tryAcquire(250);    // sem.available() == 9, returns false 企图销售250个产品,失败,因为当前只剩下14个产品


 

 
4.5、QWaitCondition
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  QT 线程