Qt信号量

■:QSemphore
    Qt中的信号量是由QSemaphore类提供的,信号量可以理解为互斥量功能的扩展,互斥量只能锁定一次而信号量可以获取多次,它可以用来保护一定数量的同种资源。
    acquire(n)函数用于获取n个资源,当没有足够的资源时调用者将被阻塞直到有足够的可用资源。release(n)函数用于释放n个资源。
    QSemaphore类还提供了一个tryAcquire(n)函数,在没有足够的资源是该函数会立即返回。

    一个典型的信号量应用程序是在两个线程间传递一定数量的数据(DataSize),而这两个线程使用一定大小(BufferSize)的共享循环缓存。

const int DataSize = 100000;
const int BufferSize = 4096;
char buffer[BufferSize];

    生产者线程向缓存中写入数据,直到它到达终点,然后在起点重新开始,覆盖已经存在的数据。消费者线程读取前者产生的数据。
    生产者、消费者实例中对同步的需求有两处,如果生产者过快的产生数据,将会覆盖消费者还没有读取的数据,如果消费者过快的读取数据,将越过生产者并且读取到一些垃圾数据。

    解决这个问题的一个有效的方法是使用两个信号量:

QSemaphore freeSpace(BufferSize);
QSemaphore usedSpace(0);

    freeSpace信号量控制生产者可以填充数据的缓存部分。usedSpace信号量控制消费者可以读取的区域。这两个信号量是互补的。其中freeSpace信号量被初始化为BufferSize(4096),表示程序一开始有BufferSize个缓冲区单元可被填充,而信号量usedSpace被初始化为0,表示程序一开始缓冲区中没有数据可供读取。
    对于这个实例,每个字节就看作一个资源,实际应用中常会在更大的单位上进行操作,从而减小使用信号量带来的开销。

void Producer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        freeSpace.acquire();
        buffer[i % BufferSize] = "MING"[uint(rand()) % 4];
        usedSpace.release();
    }
}

    在生产者中,我们从获取一个“自由的”字节开始。如果缓存被消费者还没有读取的数据填满,acquire()的调用就会阻塞,直到消费者已经开始消耗这些数据为止。一旦我们已经获取了这个字节,我们就用一些随机数据("M"、"I"、"N"或"G")填充它并且把这个字节释放为“使用的”,所以它可以被消费者线程使用。

void Consumer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        usedSpace.acquire();
        cerr << buffer[i % BufferSize];
        freeSpace.release();
    }
    cerr << endl;
}

    在消费者中,我们从获取一个“使用的”字节开始。如果缓存中没有包含任何可读的数据,acquire()调用将会阻塞,直到生产者已经产生一些数据。一旦我们已经获取了这个字节,我们就打印它并且把这个字节释放为“自由的”,使它可以被生产者使用来再次填充数据。

int main()
{
    Producer producer;
    Consumer consumer;
    producer.start();
    consumer.start();
    producer.wait();
    consumer.wait();
    return 0;
}

    main()函数的功能比较简单,负责启动生产者和消费者线程,然后等待其各自执行完毕后自动退出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值