【问题标题】:Lock for reading, writing and exclusivity锁定阅读、写作和排他性
【发布时间】:2017-10-25 05:28:05
【问题描述】:

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

  1. 读锁是一种允许你同时从不同事务中读取数据的锁,但是如果其中一个事务需要一个表来写,它需要等到所有的读锁都被移除。

  2. 写锁允许任何事务从表中读取,但只有一个拥有该表进行写入的事务才能写入表

  3. 独占锁是只有一个事务可以访问表时的锁,其他事务在锁被移除时等待。

我正在寻找如何使用 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;
};

【问题讨论】:

  • this 之类的东西能解决问题吗?

标签: c++ database transactions locking


【解决方案1】:

研究资料后,我找到了如下解决方案:

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();
}
};

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    相关资源
    最近更新 更多