繁体   English   中英

c ++中线程安全索引操作符的正确方法

[英]Correct way for thread safe indexing operator in c++

我想有线程安全的索引操作符,我带来了以下代码似乎工作。 除了边界检查之外,你能看到它的任何问题吗? 有没有更好的方法来做同样的事情(使用重载索引操作符,而不是get / set函数)?

class A
{
public:

A()
{
    for (auto i = 0; i < 100; ++i)
    {
        v[i] = i + 1;
    }
};


    class Proxy
    {
        int* val;
        A* parent;
    public:
        Proxy(int& a, A* p) : parent(p) 
        {
            parent->z.lock();
            val = &a;
        };

        ~Proxy()
        {
            parent->z.unlock();
        }

        int operator=(int a) 
        {
            *val = a;
            return a;
        };

        operator int() const
        {
            return *val;
        };
    };


int operator[](int i) const
{
    z.lock();
    int r = v[i];
    z.unlock();
    return r;
}


Proxy operator[](int i)
{
    return Proxy(v[i], this);
}


int v[100];
Z z; // some locking mechanism, not important

};

由于没有指定锁定机制,我认为它使用普通的互斥锁,在这种情况下,明显的问题是:

A a;
a[0] = a[1];

换句话说,很容易死锁程序。 使用递归互斥锁可以避免此问题。

另一个明显的问题是代码依赖于copy-elision,而不能保证永远不会发生。 如果在返回时没有删除副本,则临时将释放锁,并且副本将再次释放它,这通常是未定义的行为。 此外,访问该成员是无人看守的,并可能引入数据竞赛。 要避免此问题,您应该定义一个移动构造函数,并确保从状态移动不会尝试释放互斥锁,例如:

A::Proxy::Proxy(Proxy&& other)
    : val(other.val)
    , parent(other.parent) {
    other.parent = 0;
}
A::Proxy::~Proxy() {
    if (parent){
        parent->unlock();
    }
}

不那么明显的问题是它不太可能导致有效的实施。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM