我一直在迷恋一些无锁代码的正确性,我真的很感激我能得到的任何输入.我的问题是如何在C++ 11的内存模型中使用获取和释放语义来实现一些必需的线程间同步.在我提出问题之前,有些背景......
在MVCC中,编写者可以安装新版本的对象,而不会影响旧对象版本的读者.但是,如果编写器在具有更高编号的时间戳的读取器已获取对旧版本的引用时安装新版本的对象,则必须回滚并重试编写器事务.这是为了保持可序列化的快照隔离(因此就好像所有成功的事务以时间戳顺序一个接一个地执行).读者永远不必因为写入而重试,但如果他们的活动将"从具有更高编号的时间戳的读者"中拉出来,则可能必须回滚并重试编写者.要实现此约束,请使用读取时间戳.这个想法是读者在获取引用之前将对象的读时间戳更新为其自己的时间戳,并且编写器将检查读时间戳以查看是否可以继续该对象的新版本.
假设有两个事务:T1(写入器)和T2(读取器),它们在不同的线程中运行.
T1(作者)这样做:
void
DataStore::update(CachedObject* oldObject, CachedObject* newObject)
{
.
.
.
COcontainer* container = oldObject->parent();
tid_t newTID = newObject->revision();
container->setObject(newObject);
tid_t* rrp = &container->readRevision;
tid_t rr = __atomic_load_n(rrp, __ATOMIC_ACQUIRE);
while (true)
{
if (rr > newTID) throw TransactionRetryEx();
if (__atomic_compare_exchange_n(
rrp,
&rr,
rr,
false,
__ATOMIC_RELEASE,
__ATOMIC_RELAXED)
{
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
T2(读者)这样做:
CachedObject*
Transaction::onRead(CachedObject* object)
{
tid_t tid = Transaction::mine()->tid();
COcontainer* container = object->parent();
tid_t* rrp = &container->readRevision;
tid_t rr = …Run Code Online (Sandbox Code Playgroud)