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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用QT信号量方式进行进程间通信的例程: 首先,在发送进程中,我们需要创建一个信号量对象,并对其进行加锁操作,然后将数据写入共享内存中: ```cpp #include <QSystemSemaphore> #include <QSharedMemory> #include <QBuffer> // 创建信号量对象 QSystemSemaphore semaphore("my_semaphore", 1, QSystemSemaphore::Create); // 加锁 if (!semaphore.acquire()) { qDebug() << "Cannot acquire semaphore."; return; } // 创建共享内存对象 QSharedMemory sharedMemory("my_shared_memory"); // 打开共享内存 if (!sharedMemory.create(sizeof(int))) { qDebug() << "Cannot create shared memory segment."; semaphore.release(); return; } // 将数据写入共享内存中 QBuffer buffer; QDataStream out(&buffer); out << static_cast<int>(42); const QByteArray data = buffer.data(); memcpy(sharedMemory.data(), data.constData(), qMin(sharedMemory.size(), data.size())); // 解锁 semaphore.release(); ``` 然后,在接收进程中,我们需要打开信号量和共享内存,并对信号量进行加锁操作,然后从共享内存中读取数据: ```cpp #include <QSystemSemaphore> #include <QSharedMemory> #include <QBuffer> // 创建信号量对象 QSystemSemaphore semaphore("my_semaphore", 1, QSystemSemaphore::Open); // 加锁 if (!semaphore.acquire()) { qDebug() << "Cannot acquire semaphore."; return; } // 创建共享内存对象 QSharedMemory sharedMemory("my_shared_memory"); // 打开共享内存 if (!sharedMemory.attach()) { qDebug() << "Cannot attach shared memory segment."; semaphore.release(); return; } // 从共享内存中读取数据 QBuffer buffer; const char *data = static_cast<const char*>(sharedMemory.constData()); buffer.setData(data, sharedMemory.size()); int value; QDataStream in(&buffer); in >> value; qDebug() << "Received value:" << value; // 解锁 semaphore.release(); ``` 以上例程中,我们创建了一个名为“my_semaphore”的信号量对象和一个名为“my_shared_memory”的共享内存对象,然后在发送进程中对信号量进行加锁操作,写入一个整数值到共享内存中,接着在接收进程中对信号量进行加锁操作,从共享内存中读取整数值并输出,最后解锁信号量。 需要注意的是,信号量方式的进程间通信需要保证多个进程都能够访问同一个信号量对象,因此需要使用相同的信号量名称。在访问共享内存时也需要进行同步控制,以避免数据竞争问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值