读写锁的实现!

来源:互联网 发布:戴维斯双杀 知乎 编辑:程序博客网 时间:2024/04/28 19:03

写程序过程中总免不了用到锁,虽然大牛们总是推荐无锁编程,但那境界对我来说实在太远了。

项目中的数据资源的访问,少不了锁,考虑到都是读的多,写的少,于是参考网络,自己实现一个写优先的读写锁。

Windows下的:

class RWLock
{
    public:
        RWLock();

        ~RWLock();
        void readLock();
        void readUnlock();

        void writeLock();
        void writeUnlock();
    private:
        CEvent* eventRead;
        CEvent* eventWrite;

        CMutex* m_pMutex;
        unsigned long waittoread,waittowrite;
        unsigned long reader,writer;
};

#include "rwlock.h"

RWLock::RWLock()
{
    eventRead=new CEvent(true,true);
    eventWrite=new CEvent(true,false);
    m_pMutex=new CMutex();

    eventRead->SetEvent();
    eventWrite->SetEvent();

    waittoread=0;
    waittowrite=0;
    reader=0;
    writer=0;
}

RWLock::~RWLock()
{
}

void RWLock::readLock()
{
    bool loop=false;
    do{
        WaitForSingleObject(eventRead->m_hObject,INFINITE);
        m_pMutex->Lock();
        if (writer>0 || waittowrite>0)
        {
            loop=true;
        }else{
            reader++;
            loop=false;
            eventWrite->ResetEvent();
        }
        m_pMutex->Unlock();
    }while(loop);

}

void RWLock::readUnlock()
{
    m_pMutex->Lock();
    reader--;

    if ( reader==0)
    {
        eventWrite->SetEvent();
    }
    m_pMutex->Unlock();   
}

void RWLock::writeLock()
{
    bool loop=false;
    m_pMutex->Lock();
        waittowrite++;
        eventRead->ResetEvent();
    m_pMutex->Unlock();

    do {
        WaitForSingleObject(eventWrite->m_hObject,INFINITE);
        m_pMutex->Lock();
        if (reader>0)
        {
            loop=true;
        }else{
            loop=false;
            writer++;
            waittowrite--;
        }
        m_pMutex->Unlock();
    } while(loop);
    m_pMutex->Unlock();   
}

void RWLock::writeUnlock()
{
    m_pMutex->Lock();
    writer--;

    eventWrite->SetEvent();
    if(waittowrite<=0)
        eventRead->SetEvent();
    m_pMutex->Unlock();   
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Linux下的:

class RWLock
{
    public:
        RWLock();

        ~RWLock();
        int readLock();
        int readUnlock();

        int writeLock();
        int writeUnlock();
    private:
        pthread_mutex_t    mutex;
        pthread_cond_t    readq,writeq;
        unsigned long waittoread,waittowrite;
        unsigned long reader,writer;
};

 

 

#include "rwlock.h"

RWLock::RWLock()
{
    pthread_mutex_init ( &mutex,NULL );
    pthread_cond_init ( &readq,NULL );
    pthread_cond_init ( &writeq,NULL );

    waittoread=0;
    waittowrite=0;
    reader=0;
    writer=0;
}

RWLock::~RWLock()
{
    pthread_mutex_destroy ( &mutex );
    pthread_cond_destroy ( &readq );
    pthread_cond_destroy ( &writeq );
}

int RWLock::readLock()
{
    int value=0;
    value=pthread_mutex_lock ( &mutex );
    if ( value!=0 )
        return value;

    while ( writer>0 || waittowrite>0 )
    {
        waittoread++;

        pthread_cond_wait ( &readq,&mutex );

        waittoread--;
    }

    reader++;

    pthread_mutex_unlock ( &mutex );
}

int RWLock::readUnlock()
{
    int value=0;
    value=pthread_mutex_lock ( &mutex );
    if ( value!=0 )
        return value;

    reader--;

    if ( reader==0 && waittowrite>0 )
    {
        pthread_cond_signal ( &writeq );
    }

    pthread_mutex_unlock ( &mutex );
}

int RWLock::writeLock()
{
    int value=0;
    value=pthread_mutex_lock ( &mutex );
    if ( value!=0 )
        return value;

    while ( reader+writer>0 )
    {
        waittowrite++;
        pthread_cond_wait ( &writeq,&mutex );
        waittowrite--;
    }
    writer++;
    pthread_mutex_unlock(&mutex);   
}

int RWLock::writeUnlock()
{
    int value=0;
    value=pthread_mutex_lock ( &mutex );
    if ( value!=0 )
        return value;

    writer--;

    if(waittowrite>0)
        pthread_cond_signal(&writeq);
    else if(waittoread>0)
        pthread_cond_broadcast(&readq);

    pthread_mutex_unlock(&mutex);
}

 

用起来,没出什么大问题。不过,似乎还有可以优化的地方,比如Windows下的那个,应该可以将锁去掉,换成互斥代码段,据说互斥代码段比锁效率高点。而且这个锁不支持二次加锁,这个还没想好有什么简单的实现。

锁的实现并不是什么大问题,毕竟一些系统都有提供。锁的粒度,就没那么好处理了。工作中碰到的情况是,四个类A,B,C,D,A对A,A对B,B对C,都是一对多的关系,C对D是多对多的关系。觉得使用数据库太浪费,于是自己维护,在内存中组织成一颗树。如果简单的几个锁,那就会出现太多的等待,如果每个对象都单独分配一个锁,那锁就太多了,太多的内核对象,好像不是什么好现象。不知道数据库怎么实现的。

想到一个解决办法,就是单独启一个线程作数据的访问和修改操作,操作请求都封装成统一格式。其它线程要访问时就封装请求,放入队列,然后sleep。数据操作线程从队列中取出请求执行后,唤醒等待的线程。这样锁的需求就只剩一个了---队列。但省下锁,却换成了线程的频繁切换。在并发场合,单独一个操作线程,说不定还会成为性能瓶颈,难道要弄成一个线程池,让线程数随队列里的请求数量动态变化?额的神啊。

不知道hibernate怎么实现的。看来应该找时间好好看看。

原创粉丝点击