包含C ++中所有同步方法的类

时间:2016-03-02 02:46:15

标签: c++ multithreading c++98

在Java中,我们可以创建一个类

class Test {
    public synchronized void  fn1() {

    }

    public synchronized void  fn2() {

    }

    public synchronized void  fn3() {
        fn1(); // Calling another method
    }
}

在C ++中如果我想以一种方式模仿功能

class Test {
    private:
        mutex obj;
    public:
       void fn1(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn1Helper();
            else
                unique_lock<mutex> lock(obj);
                fn1Helper();
        }

       void fn2(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn2Helper();
            else
                unique_lock<mutex> lock(obj);
                fn2Helper();
        }

        void fn3(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn3Helper();
            else {
                unique_lock<mutex> lock(obj);
                fn3Helper();
            } 
        }
    private:
        void fn1Helper() {
        }

        void fn2Helper() {
        }

        void fn3Helper() {
             fn1(true);
        }
}
int main() {
    Test obj;
    obj.fn1();
    obj.fn2(); 
    // i.e from outside the class the methods are called with calledFromWithinClass as false.
}

简而言之,我所要做的就是使用RAII进行锁定以及允许函数相互调用。在没有calledFromWithinClass标志的C ++中,如果外部函数已获得锁定,则内部函数无法获取锁定并且代码会被卡住。

正如您所看到的,代码很复杂,还有其他方法可以在C ++中执行此操作。

我只能使用C ++ 98,你可以假设类中的所有方法都是同步的(即需要锁定)

1 个答案:

答案 0 :(得分:3)

我可以提出两个选择:

  1. 只需改为使用boost::recursive_mutex(或在C ++ 11中使用std::recursive_mutex)。

  2. (更好)始终从同步代码中调用非同步的私有实现:

    class Test {
    private:
        mutex obj;
    public:
       void fn1() {
            unique_lock<mutex> lock(obj);
            fn1Helper();
        }
    
       void fn2(bool calledFromWithinClass = false) {
            unique_lock<mutex> lock(obj);
            fn2Helper();
        }
    
    private:
        void fn1Helper() {
        }
    
        void fn2Helper() {
            fn1Helper();
        }
    }