同步对象

时间:2019-06-06 12:02:42

标签: c++ multithreading synchronization

具有具有广泛API列表的对象。

同步该对象的最佳方法是什么,即该对象已经存在于旧版代码中,并且已在数百行代码中使用。

天真的方法是使用std::mutex将每个API调用包装到对象。有没有更简单或更优雅的方法呢?

我尝试使用下面的代码,但是想征询它的意见或其他解决方案。

下面是模板包装器类,它在使用过程中自动锁定对象。即在创建对象时将其锁定,在破坏对象时将其解锁。

此模式与作用域锁定非常相似,但是它仅对静态对象/单例有用,不适用于给定对象的不同实例

template <typename T> class Synced
{
    static std::mutex _lock;
    T& _value;
    public:
    Synced(T& val) : _value(val)
    {
        std::cout << "lock" << endl;
        _lock.lock();
    }

    virtual ~Synced()
    {
        std::cout << "unlock" << endl;
        _lock.unlock();
    }

    T& operator()()
    {
        return _value;
    }
};

template <class T> std::mutex Synced<T>::_lock;

与同步模板类一起使用的示例类  这可能是上面提到的带有数十个API的类的示例

class Board
{
    public:
    virtual ~Board() { cout << "Test dtor " << endl; }
    void read() { cout << "read" << endl; }
    void write() { cout << "write" << endl; }
    void capture() { cout << "capture" << endl; }

};

用法示例,基本调用,Synced对象不受范围限制,因此析构函数将在分号后立即调用

int main(int argc, char* argv[]) 
{
    Board b;


    Synced<Board>(t)().read();
    cout <<"  " <<  endl;

    Synced<Board>(t)().write();
    cout << "  " << endl;

    Synced<Board>(t)().capture();
    cout << "  " << endl;

    return 1;
}

以下是上述示例运行的输出:

lock
read
unlock

lock
write
unlock

lock
capture
unlock

Test dtor

1 个答案:

答案 0 :(得分:0)

仅当我控制所有可能的错误条件时,我才将互斥锁用于非常小的关键部分,可能只需要几行代码。对于复杂的API,您可能最终使/互斥锁处于意外状态。我倾向于使用reactor pattern解决这类问题。是否可行取决于您是否可以对此对象合理地使用序列化/反序列化。如果您必须自己编写序列化,请考虑诸如API稳定性和复杂性之类的事情。我个人更喜欢zeromq,因为这种东西在实际中使用时,您的行程可能会有所不同。