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 - 锁定保护和返回对对象的不可分配引用的安全性的主要内容,如果未能解决你的问题,请参考以下文章