给出以下代码,

class MyCriticalSection : protected CRITICAL_SECTION
{
public:
    MyCriticalSection()
    {
        InitializeCriticalSection(this);
        EnterCriticalSection(this);
    }
    ~MyCriticalSection()
    {
        LeaveCriticalSection(this);
        DeleteCriticalSection(this);
    }
};

class MyClass
{
public:
    MyClass() : m_Int(0) {}

    int GetNum()
    {
        MyCriticalSection myCriticalSectionA;  // LockA

        return m_Int;
    }

    int SetNum(int i)
    {
        MyCriticalSection myCriticalSectionB;  // LockB

        m_Int = i;
    }
protected:
    int m_Int;
};

我认为上述设计是正确的,如果发现一些错误,请纠正我。
LockA的用法有两个功能:1>它防止由多个线程同时调用GetNum函数。 2>防止GetNum和SetNum函数同时访问m_Int。

这是我的问题:
变量myCriticalSectionA和myCriticalSectionB是类MyCriticalSection的两个不同实例。他们为什么可以彼此协作,以便锁定机制按预期工作?

我的猜测是CRITICAL_SECTION以某种方式具有一些静态标志,以便它的不同实例可以相互通信。

如果我错了,请纠正我。

====更新====
class MyCriticalSection : protected CRITICAL_SECTION
{
public:
    MyCriticalSection()
    {
        InitializeCriticalSection(this);

    }
    ~MyCriticalSection()
    {
        DeleteCriticalSection(this);
    }
    void Lock()
    {
        EnterCriticalSection(this);
    }
    void UnLock()
    {
        LeaveCriticalSection(this);
    }
};

class MyClass
{
public:
    MyClass() : m_Int(0) {}

    int GetNum()
    {
        m_Lock.Lock();
        // do something here
        m_Lock.UnLock();
        return m_Int;
    }

    int SetNum(int i)
    {
        m_Lock.Lock();
        m_Int = i;
        m_Lock.UnLock();
    }
protected:
    int m_Int;
    MyCriticalSection m_Lock;
};

谢谢

最佳答案

您的更新再好不过了。如果您想以RAII风格进行操作,则需要加倍努力。关键是您需要分离静态分配的关键部分对象和所有需要保护的块的本地锁。

以下是Jonathan Dodds的内容,但它是经典模式。

class CriticalSection
{
public:
    CriticalSection()
        { ::InitializeCriticalSection(&m_rep); }
    ~CriticalSection()
        { ::DeleteCriticalSection(&m_rep); }

    void Enter()
        { ::EnterCriticalSection(&m_rep); }
    void Leave()
        { ::LeaveCriticalSection(&m_rep); }

private:
    // copy ops are private to prevent copying
    CriticalSection(const CriticalSection&);
    CriticalSection& operator=(const CriticalSection&);

    CRITICAL_SECTION m_rep;
};

尽管您可以通过继承CRITICAL_SECTION来实现此目的,但我认为封装更合适。

接下来定义锁:
class CSLock
{
public:
    CSLock(CriticalSection& a_section)
        : m_section(a_section) { m_section.Enter(); }
    ~CSLock()
        { m_section.Leave(); }

private:
    // copy ops are private to prevent copying
    CSLock(const CSLock&);
    CSLock& operator=(const CSLock&);

    CriticalSection& m_section;
};

最后是用法示例:
class Example
{
public:
    bool Process( … );

    …

private:
    CriticalSection m_criticalsection;

    …
};

bool Example::Process( … )
{
    CSLock lock(m_critsection);

    // do some stuff
    …
}

关键是关键部分的单个实例在所有线程之间共享。这就是使关键部分起作用的原因。

与此相反,可能存在许多CSLock实例,它们都同时存在于同一关键部分。这允许Process()方法被许多线程调用,但是在单个共享关键节上采用的CSLock实例的生命周期内将其代码序列化。

关于c++ - 有关CRITICAL_SECTION的用法的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5421387/

10-11 18:13