C ++,Qt - 锁定保护和返回对对象的不可分配引用的安全性

Posted

技术标签:

【中文标题】C ++,Qt - 锁定保护和返回对对象的不可分配引用的安全性【英文标题】:C++, Qt - lock guard and the safety of returning an unassignable reference to an object 【发布时间】:2020-04-30 20:35:44 【问题描述】:

假设以下场景:

我已经实现了自己的 QReadWriteLockGuard:

class QReadWriteLockGuard 
public:
    explicit QReadWriteLockGuard(QReadWriteLock & m) : m(m) m.lockForRead();
    ~QReadWriteLockGuard() m.unlock();

    QReadWriteLockGuard(QReadWriteLockGuard const &) = delete;
    void operator=(QReadWriteLockGuard &) = delete;

private:
    QReadWriteLock & m;
;

我有一个“管理器”对象 A,它包含对象 B 的一个实例。

对象A有一个get_b方法:

const B& A::get_b() const

    QReadWriteLockGuard(_b_lock);
    return *_b;

现在,B当然有它的子结构:属性、公共方法等。假设另一个线程可以随时重写_b的内容,甚至删除它们,如果它们是指针的话。但是,它会先调用_b_lock.lockForWrite()

假设B 不可赋值(私有赋值和复制操作符)。这样做是否安全:

A_instance.get_b().get_vector().at(i).do_stuff()?

也就是说,读写锁是在执行do_stuff()之前还是之后解锁?或者它可能是未定义的?

【问题讨论】:

【参考方案1】:

const 引用并不意味着对象是const,只是您不能通过该引用修改对象。如果一个线程拥有 const 引用并读取它,而另一个线程写入同一个对象(通过非常量引用),那么您将发生数据竞争。

A::get_b() 返回时,您的QReadWriteLockGuard 会释放锁定,因此无济于事。

对于这一行:

A_instance.get_b().get_vector().at(i).do_stuff();

认为它或多或少等同于

const B& b = A_instance.get_b();
b.get_vector().at(i).do_stuff();

在第一行之后你已经释放了锁。

【讨论】:

以上是关于C ++,Qt - 锁定保护和返回对对象的不可分配引用的安全性的主要内容,如果未能解决你的问题,请参考以下文章

Qt 之 QBitmap

带有对象的 Qt 容器

如果堆分配的对象被销毁并重新分配指针,Qt 的信号和插槽系统会工作吗?

Qt之emitsignalsslot的使用

C/C++线程安全型队列的实现

2021-04-15qt对xlsx文件的读取