IPC学习,利用互斥体和条件变量实现读者和写者问题

#include <boost/thread.hpp>

class rwMutex
{
private:
    boost::mutex lockMutex;                         // 同步控制互斥变量,控制对标志量得访问
    boost::condition_variable_any condWriter;       // 写者条件变量
    boost::condition_variable_any condReader;       // 读者条件变量
    unsigned long waitWriter;                       // 记录写者等待数
    unsigned long waitReader;                       // 记录读者等待数

// 进入缓冲区标志,holder = -1,读者在缓冲区; holder = 0,均不在缓冲区; holder > 0,有多个读者在缓冲区
    long holder;                                    
    const bool priority;                            // priority = true,写者优先; false 读者优先,默认是写者优先

private:
    rwMutex& operator= ( const rwMutex&);
    rwMutex(const rwMutex&);

public:
    rwMutex( const bool flag = true );
    void rdlock();               // 读者占锁
    void wrlock();               // 写者占锁
    void unrdlock();             // 读者释放锁
    void unwrlock();             // 写者释放锁
};

rwMutex::rwMutex( const bool flag )
:waitWriter(0),
 waitReader(0),
 holder(0),
 priority(flag)
{}

void rwMutex::rdlock()
{
    boost::mutex::scoped_lock innerLock(lockMutex);

    // 有写者存在,则直接阻塞
    while(holder < 0)
    {
        ++waitReader;
        condReader.wait(lockMutex);
        --waitReader;
    }

    // 没有人占有资源
    if(0 == holder)
    {
        if(priority)
        {
            while(waitWriter >0)
            {
                ++waitReader;
                condReader.wait(lockMutex);
                --waitReader;
            }
        }
    }

    // 读者占有资源,直接进入
    ++holder;
}

void rwMutex::wrlock()
{
    boost::mutex::scoped_lock innerLock(lockMutex);

    // 有读者或者是写者占有资源
    while (0 != holder)
    {
        ++waitWriter;
        condWriter.wait(lockMutex);
        --waitWriter;
    }

    // 没有人占有资源,但是可能有等待者
    if(!priority)
    {
        while(waitReader >0)
        {
            ++waitWriter;
            condWriter.wait(lockMutex);
            --waitWriter;
        }
    }

    holder = -1;
}

void rwMutex::unrdlock()
{
    {
        boost::mutex::scoped_lock innerLock(lockMutex);
        --holder;
    }

    // 写者一定是阻塞的,直到hodler=0的时候才会通知写着,所以无论是哪个读者线程发出通知都不要紧
    if (0 == holder && waitWriter >0)
        condWriter.notify_one();
}

void rwMutex::unwrlock()
{
    {
        boost::mutex::scoped_lock innerLock(lockMutex);
        holder = 0;
    }

    // 之所以放在锁的外面是因为:如果有写者操作,那么读者和写者必定会全部阻塞,那么要唤醒一个等待的子线程
    // 就需要我们显示通知,所以可以放在外面,同时避免了通知后因为没有释放锁,读者或者写者需要等待

    // 读者退出,如果写者优先
    if (priority)
    {
        if (waitWriter >0)
            condWriter.notify_one();
        else if (waitReader >0)
            condReader.notify_all();  // 因为读者可以并入
    }
    else
    {
        // 如果是读者优先
        if (waitReader >0)
            condReader.notify_all();
        else if (waitWriter >0)
            condWriter.notify_one();
    }
}

class readerLock
{
private:
    rwMutex &mutex;

public:
    readerLock(rwMutex &m)
        :mutex(m)
    {
        mutex.rdlock();
    }

    ~readerLock()
    {
        mutex.unrdlock();
    }
};

class writerLock
{
private:
    rwMutex &mutex;

public:
    writerLock(rwMutex &m)
        :mutex(m)
    {
        mutex.wrlock();
    }

    ~writerLock()
    {
        mutex.unwrlock();
    }
};

rwMutex myMutex;
boost::mutex iomutex;

void reader()
{
    readerLock lock(myMutex);
    boost::mutex::scoped_lock iolock(iomutex);
    std::cout << "reader inside buffer,my thread id = " << boost::this_thread::get_id() << "\n";      
}

void writer()
{
    writerLock lock(myMutex);
    std::cout << "writer inside buffer,my thread id = " << boost::this_thread::get_id() << "\n";
}

int main( int argc, char *argv )
{
    boost::thread_group gr;
    gr.create_thread(writer);
    gr.create_thread(writer);
    gr.create_thread(writer);

    gr.create_thread(reader);
    gr.create_thread(reader);
    gr.create_thread(reader);


    gr.create_thread(writer);
    gr.create_thread(writer);
    gr.create_thread(writer);

    gr.create_thread(reader);
    gr.create_thread(reader);
    gr.create_thread(reader);


    gr.create_thread(writer);
    gr.create_thread(writer);
    gr.create_thread(writer);

    gr.join_all();
    return 0;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值