• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    5年前 (2013-05-07)  QT |   抢沙发  9 
    文章评分 0 次,平均分 0.0

    线程同步

    QMutex, QReadWriteLock, QSemaphore, QWaitCondition 提供了线程同步的手段。使用线程的主要想法是希望它们可以尽可能并发执行,而一些关键点上线程之间需要停止或等待。例如,假如两个线程试图同时访问同一个全局变量,结果可能不如所愿。
    QMutex 提供相互排斥的锁,或互斥量。在一个时刻至多一个线程拥有mutex,假如一个线程试图访问已经被锁定的mutex,那么它将休眠,直到拥有mutex的线程对此mutex解锁。Mutexes常用来保护共享数据访问。
    QReadWriterLock 与QMutex相似,除了它对 "read","write"访问进行区别对待。它使得多个读者可以共时访问数据。使用QReadWriteLock而不是QMutex,可以使得多线程程序更具有并发性。

    QReadWriteLock lock;
    void ReaderThread::run()
    {
        // ...
         lock.lockForRead();
         read_file();
         lock.unlock();
         //...
    }
    void WriterThread::run()
    {
       // ...
         lock.lockForWrite();
         write_file();
         lock.unlock();
        // ...
    }

    QSemaphore 是QMutex的一般化,它可以保护一定数量的相同资源,与此相对,一个mutex只保护一个资源。下面例子中,使用QSemaphore来控制对环状缓冲的访问,此缓冲区被生产者线程和消费者线程共享。生产者不断向缓冲写入数据直到缓冲末端,再从头开始。消费者从缓冲不断读取数据。信号量比互斥量有更好的并发性,假如我们用互斥量来控制对缓冲的访问,那么生产者,消费者不能同时访问缓冲。然而,我们知道在同一时刻,不同线程访问缓冲的不同部分并没有什么危害。

    const int DataSize = 100000;
    const int BufferSize = 8192;
    char buffer[BufferSize];
    QSemaphore freeBytes(BufferSize);
    QSemaphore usedBytes;
    class Producer : public QThread
    {
    public:
         void run();
    };
    void Producer::run()
    {
         qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
         for (int i = 0; i < DataSize; ++i) {
             freeBytes.acquire();
             buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
             usedBytes.release();
         }
    }
    class Consumer : public QThread
    {
    public:
         void run();
    };
    void Consumer::run()
    {
         for (int i = 0; i < DataSize; ++i) {
             usedBytes.acquire();
             fprintf(stderr, "%c", buffer[i % BufferSize]);
             freeBytes.release();
         }
         fprintf(stderr, "\n");
    }
    int main(int argc, char *argv[])
    {
         QCoreApplication app(argc, argv);
         Producer producer;
         Consumer consumer;
         producer.start();
         consumer.start();
         producer.wait();
         consumer.wait();
         return 0;
    }

    QWaitCondition 允许线程在某些情况发生时唤醒另外的线程。一个或多个线程可以阻塞等待一QWaitCondition ,用wakeOne()或wakeAll()设置一个条件。wakeOne()随机唤醒一个,wakeAll()唤醒所有。

    下面的例子中,生产者首先必须检查缓冲是否已满(numUsedBytes==BufferSize),如果是,线程停下来等待bufferNotFull条件。如果不是,在缓冲中生产数据,增加numUsedBytes,激活条件 bufferNotEmpty。使用mutex来保护对numUsedBytes的访问。另外,QWaitCondition::wait()接收一个mutex作为参数,这个mutex应该被调用线程初始化为锁定状态。在线程进入休眠状态之前,mutex会被解锁。而当线程被唤醒时,mutex会处于锁定状态,而且,从锁定状态到等待状态的转换是原子操作,这阻止了竞争条件的产生。当程序开始运行时,只有生产者可以工作。消费者被阻塞等待bufferNotEmpty条件,一旦生产者在缓冲中放入一个字节,bufferNotEmpty条件被激发,消费者线程于是被唤醒。

    const int DataSize = 100000;
    const int BufferSize = 8192;
    char buffer[BufferSize];
    QWaitCondition bufferNotEmpty;
    QWaitCondition bufferNotFull;
    QMutex mutex;
    int numUsedBytes = 0;
    class Producer : public QThread
    {
    public:
         void run();
    };
    void Producer::run()
    {
         qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
         for (int i = 0; i < DataSize; ++i) {
             mutex.lock();
             if (numUsedBytes == BufferSize)
                 bufferNotFull.wait(&mutex);
             mutex.unlock();
             buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
             mutex.lock();
             ++numUsedBytes;
             bufferNotEmpty.wakeAll();
             mutex.unlock();
         }
    }
    class Consumer : public QThread
    {
    public:
         void run();
    };
    void Consumer::run()
    {
         for (int i = 0; i < DataSize; ++i) {
             mutex.lock();
             if (numUsedBytes == 0)
                 bufferNotEmpty.wait(&mutex);
             mutex.unlock();
             fprintf(stderr, "%c", buffer[i % BufferSize]);
             mutex.lock();
             --numUsedBytes;
             bufferNotFull.wakeAll();
             mutex.unlock();
         }
         fprintf(stderr, "\n");
    }
    int main(int argc, char *argv[])
    {
         QCoreApplication app(argc, argv);
         Producer producer;
         Consumer consumer;
         producer.start();
         consumer.start();
         producer.wait();
         consumer.wait();
         return 0;
    }
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/1053.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享