开发者

QSemaphore producer consumer problem

This is more or less Qt's example with some small changes.

The output is PcPcPcPc...etc. I don't understand why.

Namely, I am confused about how sProducer.acquire(256); works. I believe I understand how sProducer.acquire(1); works. It doesn't make sense to me to acquire anything more than 1 because I don't see how acquiring more than 1 makes any differ开发者_StackOverflow社区ence logically. Could someone explain this? On the surface, writing 1 byte and reading 1 byte doesn't seem very efficient due to semaphore overhead...but acquiring more resources doesn't seem to make a performance difference nor does the code make sense.

Logically I think both the acquire and release have to have the same number (whatever that number is). But how can I modify this code so I can acquire more (say 256) and thus reduce semaphore overhead? The code bellow just doesn't make sense to me when acquire and release is not 1.

#include <QtCore>
#include <iostream>
#include <QTextStream>

//Global variables.
QTextStream out(stdout);
QTextStream in(stdin);

const int DataSize = 1024; 
const int BufferSize = 512;
char buffer[BufferSize];    

QSemaphore sProducer(BufferSize);
QSemaphore sConsumer(0);
//-----------------------------

class Producer : public QThread
{
public:
    void run();
};

void Producer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        sProducer.acquire(256);
        buffer[i % BufferSize] = 'P';
        sConsumer.release(256);
    }
}

class Consumer : public QThread
{
public:
    void run();
};

void Consumer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        sConsumer.acquire(256);
        std::cerr << buffer[i % BufferSize];
        out << "c";
        out.flush();
        sProducer.release(256);
    }
    std::cerr << std::endl;
}

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

    in.readLine();  //so i can read console text.
    return 0;
}


Since there is only one producer and one consumer, they can move freely their own private cursor, their i variable, of the amount of bytes they want, as long as there is enough room to do that (something higher that 256 on both sides with a 512 buffer would cause a deadlock).

Basically, when a thread successfully acquire 256 bytes, it means it can safely read or write these 256 bytes in one single operation, so you just have to put another loop inside the acquire/release block to handle that number of bytes.

For the producer:

void Producer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        const int blockSize = 256;
        sProducer.acquire(blockSize);
        for(int j = 0; j < blockSize; ++i, ++j) {
            buffer[i % BufferSize] = 'P';
        }
        sConsumer.release(blockSize);
    }
}

And for the consumer

void Consumer::run()
{
    for (int i = 0; i < DataSize; ++i) {
        const int blockSize = 128;
        sConsumer.acquire(blockSize);
        for(int j = 0; j < blockSize; ++i, ++j) {
            std::cerr << buffer[i % BufferSize];
            out << "c";
            out.flush();
        }
        sProducer.release(blockSize);
    }
    std::cerr << std::endl;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜