读写锁总结

参看我前一篇文章:http://blog.csdn.net/tifentan/article/details/78949028

这里再提供一个跨平台的简单实现

//完成读写锁初始化
CRWLock::CRWLock()
{

    InitRWLock();

}

//
CRWLock::~CRWLock()
{
    DestroyRWLock();
}

BOOL  CRWLock::MyWaitForSingleObject(HANDLE hObject)
{
#ifdef WIN32

    DWORD result;

    result = WaitForSingleObject(hObject, INFINITE);

    return (result == WAIT_OBJECT_0);

#endif
}

BOOL  CRWLock::InitRWLock()
{
#ifdef WIN32

    m_RWLock.nReaderCount = 0;
    m_RWLock.hDataLock = CreateSemaphore(NULL, 1, 1, NULL);
    if (m_RWLock.hDataLock == NULL)
    {
        return FALSE;
    }

    m_RWLock.hMutex = CreateMutex(NULL, FALSE, NULL);
    if (m_RWLock.hMutex == NULL)
    {
        CloseHandle(m_RWLock.hDataLock);
        return FALSE;
    }

    return TRUE;

#else

     pthread_rwlock_init(&m_RWLock, NULL);

     return TRUE;
#endif

}

BOOL  CRWLock::DestroyRWLock()
{
#ifdef WIN32

    DWORD result = WaitForSingleObject(m_RWLock.hDataLock, INFINITE);
    if (result != WAIT_OBJECT_0)
    {
        return FALSE;
    }

    CloseHandle(m_RWLock.hMutex);
    CloseHandle(m_RWLock.hDataLock);
    return TRUE;

#else

    pthread_rwlock_destroy(&m_RWLock);

    return TRUE;

#endif
}

BOOL CRWLock::AcquireReadLock()
{
    BOOL result = TRUE;

#ifdef WIN32

    if (MyWaitForSingleObject(m_RWLock.hMutex) == FALSE)
    {
        return FALSE;
    }

    m_RWLock.nReaderCount ++;
    if(m_RWLock.nReaderCount == 1)
    {
        result = MyWaitForSingleObject(m_RWLock.hDataLock);
    }

    ReleaseMutex(m_RWLock.hMutex);

    return result;

#else
    pthread_rwlock_rdlock(&m_RWLock);

    return result;
#endif
}


BOOL CRWLock::ReleaseReadLock()
{
    int result = TRUE;

#ifdef WIN32

    LONG lPrevCount;

    if (MyWaitForSingleObject(m_RWLock.hMutex) == FALSE)
    {
        return FALSE;
    }

    --m_RWLock.nReaderCount;

    if (m_RWLock.nReaderCount == 0)
    {
        result = ReleaseSemaphore(m_RWLock.hDataLock, 1, &lPrevCount);
    }

    ReleaseMutex(m_RWLock.hMutex);

    return result;
#else

    return pthread_rwlock_unlock(&m_RWLock);    

#endif
}

BOOL CRWLock::AcquireWriteLock()
{

#ifdef WIN32

    return MyWaitForSingleObject(m_RWLock.hDataLock);

#else

    return pthread_rwlock_wrlock(&m_RWLock);

#endif
}


BOOL CRWLock::ReleaseWriteLock()
{
#ifdef WIN32

    int result = TRUE;
    LONG lPrevCount;

    result = ReleaseSemaphore(m_RWLock.hDataLock, 1, &lPrevCount);
    if (lPrevCount != 0)
    {
        return FALSE;
    }

    return result;

#else
    return  pthread_rwlock_unlock(&m_RWLock);
#endif
}

然而这个是有问题的,多个读线程高频率读,写锁有可能进入不了。
解决方法是再建立一个mutex来管理资源状态,确认有更新数据才进入读锁。

关于读写的优先问题

以下两种情况下读写请求会进行竞争:
1.释放写锁后
2.在读锁状态下,有写锁请求会等待,之后再有新的读锁请求将一同等待,当读锁状态释放后

会不会同时有读写锁请求的情况下,优先写锁会好点呢?
上篇文章是公平竞争的,如果要求写优先,可参考https://www.cnblogs.com/kuliuheng/p/4065304.html的linux部分,关键在于使用到一个状态锁,两个条件事件。
修改后代码如下:

//写优先读写锁
class RWLockAdv
{
private:
    int _st;
    int _rlockCount;
    int _rwaitingCount;
    int _wwaitingCount;
    HANDLE _wev;
    HANDLE _rev;
#ifdef CROSS_PROCESS_IPC
    HANDLE _stLock;
#else
    CRITICAL_SECTION _stLock;
#endif

public:
    RWLockAdv(void);
    ~RWLockAdv(void);
    void rlock();
    void wlock();
    void unlock();
};

#define RWLOCK_IDLE 0    
#define RWLOCK_R 0x01    
#define RWLOCK_W 0x02    



RWLockAdv::RWLockAdv(void)
    : _rlockCount(0),
    _st(RWLOCK_IDLE),
    _rwaitingCount(0),
    _wwaitingCount(0)
{
#ifdef CROSS_PROCESS_IPC
    _stLock = CreateMutex(NULL, FALSE, NULL);
    assert(_stLock != INVALID_HANDLE_VALUE);
#else
    InitializeCriticalSection(&_stLock);
#endif

    _wev = CreateEvent(NULL, TRUE, FALSE, NULL);
    assert(_wev != INVALID_HANDLE_VALUE);
    _rev = CreateEvent(NULL, TRUE, FALSE, NULL);
    assert(_rev != INVALID_HANDLE_VALUE);
}


RWLockAdv::~RWLockAdv(void)
{
#ifdef CROSS_PROCESS_IPC
    CloseHandle(_stLock);
#else
    DeleteCriticalSection(&_stLock);
#endif
    CloseHandle(_wev);
    CloseHandle(_rev);
}

void RWLockAdv::rlock()
{
    bool isWaitReturn = false;
    while (1)
    {
#ifdef CROSS_PROCESS_IPC
        WaitForSingleObject(_stLock, INFINITE);
#else
        EnterCriticalSection(&_stLock);
#endif
        if (isWaitReturn)
        {

            --_rwaitingCount;
        }

        if (_st == RWLOCK_IDLE)
        {

            _st = RWLOCK_R;
            _rlockCount++;
#ifdef CROSS_PROCESS_IPC
            ReleaseMutex(_stLock);
#else
            LeaveCriticalSection(&_stLock);
#endif
            break;
        }
        else if (_st == RWLOCK_R)
        {
            if (_wwaitingCount > 0)
            {

                ++_rwaitingCount;
                ResetEvent(_rev);

#ifdef CROSS_PROCESS_IPC
                SignalObjectAndWait(_stLock, _rev, INFINITE, FALSE);
#else
                LeaveCriticalSection(&_stLock);
                WaitForSingleObject(_rev, INFINITE);
#endif
                isWaitReturn = true;
            }
            else
            {

                ++_rlockCount;

#ifdef CROSS_PROCESS_IPC
                ReleaseMutex(_stLock);
#else
                LeaveCriticalSection(&_stLock);
#endif
                break;
            }
        }
        else if (_st == RWLOCK_W)
        {

            ++_rwaitingCount;
            ResetEvent(_rev);

#ifdef CROSS_PROCESS_IPC
            SignalObjectAndWait(_stLock, _rev, INFINITE, FALSE);
#else
            LeaveCriticalSection(&_stLock);
            WaitForSingleObject(_rev, INFINITE);
#endif

            isWaitReturn = true;
        }
        else
        {
            assert(0);
            break;
        }
    }
}

void RWLockAdv::wlock()
{
    bool isWaitReturn = false;

    while (1)
    {
#ifdef CROSS_PROCESS_IPC
        WaitForSingleObject(_stLock, INFINITE);
#else
        EnterCriticalSection(&_stLock);
#endif

        if (isWaitReturn) --_wwaitingCount;

        if (_st == RWLOCK_IDLE)
        {
            _st = RWLOCK_W;

#ifdef CROSS_PROCESS_IPC
            ReleaseMutex(_stLock);
#else
            LeaveCriticalSection(&_stLock);
#endif
            break;
        }
        else
        {
            ++_wwaitingCount;
            ResetEvent(_wev);
#ifdef CROSS_PROCESS_IPC
            SignalObjectAndWait(_stLock, _wev, INFINITE, FALSE);
#else
            LeaveCriticalSection(&_stLock);
            WaitForSingleObject(_wev, INFINITE);
#endif


            isWaitReturn = true;
        }
    }
}

void RWLockAdv::unlock()
{
#ifdef CROSS_PROCESS_IPC
    WaitForSingleObject(_stLock, INFINITE);
#else
    EnterCriticalSection(&_stLock);
#endif
    //这代表在读状态
    if (_rlockCount > 0)
    {

        --_rlockCount;

        if (0 == _rlockCount)
        {
            _st = RWLOCK_IDLE;

            if (_wwaitingCount > 0) {
                SetEvent(_wev);
            }
            else if(_rwaitingCount > 0){
                SetEvent(_rev);
            }
            else
            {

            }
        }
        else
        {

        }
    }
    else
    {
        _st = RWLOCK_IDLE;


        //也可以改成写状态释放后优先读?
        if (_wwaitingCount > 0) {
            SetEvent(_wev);
        }
        else if (_rwaitingCount > 0) {
            SetEvent(_rev);
        }
        else
        {

        }
    }
#ifdef CROSS_PROCESS_IPC
    ReleaseMutex(_stLock);
#else
    LeaveCriticalSection(&_stLock);
#endif
}

代码没测试,待续!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redisson提供了读写锁的功能。读写锁在并发场景中非常有用,特别是对于读操作远多于写操作的情况。读写锁允许多个线程同时持有读锁,但只允许一个线程持有写锁。 通过使用Redisson的读写锁,你可以实现对某个关键字进行并发的读和写操作控制。当一个线程持有读锁时,其他线程也可以持有读锁,但是当有线程持有写锁时,其他的写锁和读锁都会被阻塞。 在实际应用中,如果有一个场景需要并发读取数据,然后并发进行扣减操作,可能会出现扣减失败的情况。这是因为在读取的时候还有库存,但是在扣减的时候库存已经没有了。为了避免这种情况,可以使用Redisson的读写锁来保证并发读写的线程安全性。 在使用Redisson的读写锁时,可以通过以下方式进行操作: - 使用`readLock()`方法获取读锁,并通过`lock()`方法加锁,然后使用`unlock()`方法释放读锁。 - 使用`writeLock()`方法获取写锁,并通过`lock()`方法加锁,然后使用`unlock()`方法释放写锁。 在你的代码示例中,可以看到使用Redisson的读写锁的具体操作。通过`getReadWriteLock(key)`方法获取读写锁,然后使用`readLock()`方法获取读锁或使用`writeLock()`方法获取写锁。最后使用`lock()`方法加锁,使用`unlock()`方法释放锁。 总结起来,Redisson的读写锁提供了一种并发控制机制,可以在并发读写场景下确保数据的一致性与线程安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [redission读写锁解决db和缓存双写不一致](https://blog.csdn.net/weixin_43944305/article/details/120191365)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值