锁定阅读,写作和排他性

时间:2017-10-25 05:28:05

标签: c++ database transactions locking

我需要实现三种不同类型的锁定。锁定阅读,写作和排他性。例如,有一个名为table的抽象对象,许多事务都在不同的线程中工作。

  1. 读锁是一种锁,它允许您同时读取来自不同事务的数据,但如果其中一个事务需要一个表进行写操作,则需要等到所有读锁都被删除。

  2. 写锁定允许任何事务从表中读取,但只有一个拥有该表用于写入的事务可以写入表

  3. 当只有一个事务可以访问该表时,独占锁是一个锁,而其他事件在锁被删除时等待。

  4. 我正在寻找如何使用WinApi和C / C ++实现这一点我正在尝试

    class Table
    {
    void LockWrite()
    {
        if (LockLW.IsLock())
            LockLW.wait_and_lock();
        //
        if (LockEx.IsLock())
            LockEx.wait();
    }
    void LockExclusive()
    {
        {
            // it is assumed that this is a thread-safe check
            if (readers != 0)
                FreeLockRead.wait();
        }
        //but there is a problem, because in this place some transactions have started to read again
    
        if (LockLW.IsLock())
            LockLW.wait_and_lock();
    
        if (LockEx.IsLock())
            LockEx.wait_and_lock();
    }
    
    void UnLockExclusive()
    {
        LockEx.unLock();
    }
    
    void LockRead()
    {
        if (LockEx.IsLock())
            LockEx.wait();
        //Set Lock Read
        //a problem, because in this place one of transactions have got LockEx
        readers += 1;
    }
    
    void UnLockRead()
    {
        readers -= 1;
        if (readers == 0)
            FreeLockRead.pulse();
    }
    
    mutex LockLW;
    mutex LockEx;
    
    event FreeLockRead;
    atomic  readers;
    };
    

1 个答案:

答案 0 :(得分:0)

在研究材料后,我找到了以下解决方案:

class Table
{
enum eFlag
{
    eFree = 0,
    eRead = 1,
    eWrite = 2,
    eExclusive = 4
};
uint32_t m_nReaders;
std::mutex m_Mutex;
uint32_t m_nFlag;
std::condition_variable m_condition;

void LockForRead()
{
    std::unique_lock<std::mutex> lk(m_Mutex);
    if (m_nFlag & eExclusive)
    {
        m_condition.wait(lk, [this]() {return !(m_nFlag & eExclusive); });
    }
    m_nReaders += 1;
    m_nFlag |= eRead;
}
void UnLockForRead()
{
    std::unique_lock<std::mutex> lk(m_Mutex);

    assert(m_nReaders != 0 && (m_nFlag & eRead));

    m_nReaders -= 1;
    if (m_nReaders == 0)
    {
        m_nFlag &= ~eRead;
        m_condition.notify_one();
    }
}
void LockForExclusive()
{
    std::unique_lock<std::mutex> lk(m_Mutex);
    if (m_nFlag != eFree)
        m_condition.wait(lk, [this]() {return m_nFlag == eFree; });

    m_nFlag = eExclusive;
}
void UnLockForExclusive()
{
    std::unique_lock<std::mutex> lk(m_Mutex);

    assert(m_nFlag == eExclusive);

    m_nFlag = eFree;
    m_condition.notify_all();
}
void LockForWrite()
{
    std::unique_lock<std::mutex> lk(m_Mutex);

    if (m_nFlag & (eExclusive | eWrite))
        m_condition.wait(lk, [this]() {return !(m_nFlag & (eExclusive | eWrite)); });

    m_nFlag |= eWrite;
}
void UnLockForWrite()
{
    std::unique_lock<std::mutex> lk(m_Mutex);

    assert(m_nFlag & eWrite);

    m_nFlag &= ~eWrite;
    m_condition.notify_one();
}
};