C++、Qt - 锁保护和返回对象的不可分配引用的安全性
C++, Qt - lock guard and the safety of returning an unassignable reference to an object
假设以下场景:
我已经实现了自己的 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;
};
我有一个 "manager" 对象 A,它包含对象 B 的一个实例。
对象 A 有一个方法 get_b:
const B& A::get_b() const
{
QReadWriteLockGuard(_b_lock);
return *_b;
}
现在,B当然有它的子结构:属性,public方法等。假设另一个线程可以随时重写_b
的内容,甚至删除它们,如果它们是指针。但是,它会先调用 _b_lock.lockForWrite()
。
假设 B
不可赋值(私有赋值和复制操作符)。这样做安全吗:
A_instance.get_b().get_vector().at(i).do_stuff()
?
也就是说,ReadWrite锁是在执行do_stuff()
之前还是之后解锁?还是未定义?
const
引用并不意味着对象是 const
,只是您不能通过该引用修改对象。如果一个线程有那个 const
引用并读取它,而另一个线程写入同一个对象(通过非常量引用),那么你就有了数据竞争。
你的QReadWriteLockGuard
在A::get_b()
returns时释放了锁,所以没有用。
对于这一行:
A_instance.get_b().get_vector().at(i).do_stuff();
认为它或多或少等同于
const B& b = A_instance.get_b();
b.get_vector().at(i).do_stuff();
在第一行之后你已经释放了锁。
假设以下场景:
我已经实现了自己的 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;
};
我有一个 "manager" 对象 A,它包含对象 B 的一个实例。
对象 A 有一个方法 get_b:
const B& A::get_b() const
{
QReadWriteLockGuard(_b_lock);
return *_b;
}
现在,B当然有它的子结构:属性,public方法等。假设另一个线程可以随时重写_b
的内容,甚至删除它们,如果它们是指针。但是,它会先调用 _b_lock.lockForWrite()
。
假设 B
不可赋值(私有赋值和复制操作符)。这样做安全吗:
A_instance.get_b().get_vector().at(i).do_stuff()
?
也就是说,ReadWrite锁是在执行do_stuff()
之前还是之后解锁?还是未定义?
const
引用并不意味着对象是 const
,只是您不能通过该引用修改对象。如果一个线程有那个 const
引用并读取它,而另一个线程写入同一个对象(通过非常量引用),那么你就有了数据竞争。
你的QReadWriteLockGuard
在A::get_b()
returns时释放了锁,所以没有用。
对于这一行:
A_instance.get_b().get_vector().at(i).do_stuff();
认为它或多或少等同于
const B& b = A_instance.get_b();
b.get_vector().at(i).do_stuff();
在第一行之后你已经释放了锁。