C 是";断言I';“我将此互斥锁保持为锁定状态”;可行吗?
年,《软件清漆》的作者对新的ISO C标准草案表示失望。特别是他认为应该有一些有用的东西,比如“断言我持有这个互斥锁”函数,他声称他在《消失》中写了一个 我查了密码。它本质上是这样的:C 是";断言I';“我将此互斥锁保持为锁定状态”;可行吗?,c,multithreading,thread-safety,pthreads,mutex,C,Multithreading,Thread Safety,Pthreads,Mutex,年,《软件清漆》的作者对新的ISO C标准草案表示失望。特别是他认为应该有一些有用的东西,比如“断言我持有这个互斥锁”函数,他声称他在《消失》中写了一个 我查了密码。它本质上是这样的: struct ilck { unsigned magic; pthread_mutex_t mtx; int held; pthread_t owner; VTAILQ_ENTRY(ilck) list; cons
struct ilck {
unsigned magic;
pthread_mutex_t mtx;
int held;
pthread_t owner;
VTAILQ_ENTRY(ilck) list;
const char *w;
struct VSC_C_lck *stat;
};
void Lck__Lock(struct ilck *ilck, const char *p, const char *f, int l)
{
if (!(params->diag_bitmap & 0x18)) {
AZ(pthread_mutex_lock(&ilck->mtx));
AZ(ilck->held);
ilck->stat->locks++;
ilck->owner = pthread_self();
ilck->held = 1;
return;
}
r = pthread_mutex_trylock(&ilck->mtx);
assert(r == 0 || r == EBUSY);
if (r) {
ilck->stat->colls++;
if (params->diag_bitmap & 0x8)
VSL(SLT_Debug, 0, "MTX_CONTEST(%s,%s,%d,%s)",
p, f, l, ilck->w);
AZ(pthread_mutex_lock(&ilck->mtx));
} else if (params->diag_bitmap & 0x8) {
VSL(SLT_Debug, 0, "MTX_LOCK(%s,%s,%d,%s)", p, f, l, ilck->w);
}
ilck->stat->locks++;
ilck->owner = pthread_self();
ilck->held = 1;
}
void
Lck__Assert(const struct ilck *ilck, int held)
{
if (held)
assert(ilck->held &&
pthread_equal(ilck->owner, pthread_self()));
else
assert(!ilck->held ||
!pthread_equal(ilck->owner, pthread_self()));
}
我省略了try-lock和unlock操作的实现,因为它们基本上是例行的。我有疑问的地方是Lck__Assert(),在这里对ilck->hold和lick->owner的访问不受任何互斥保护
因此,请按照以下事件顺序进行说明:
在我看来,应该有一些“全局”互斥体来保护互斥体自身的数据,或者至少有一些写/读屏障。我的分析正确吗?我已经联系了作者。他说我的分析是有效的,并且使用memset(,0,)来取消设置“thread\t owner”,因为thread\t不是具有指定赋值运算符的透明结构。希望这在大多数平台上都有效。我看不到解锁代码。我认为这是正确的,重置了所有者。考虑到多线程设计的广度和复杂性以及与之相关的问题,我敢肯定,像这样的东西提供的功能,即使在所有平台上都能工作,也不值得。我觉得你链接到的博客有点可怜。他反对使用像
\u Noreturn
这样的关键词,并将它们与Noreturn
混在一起,这表明他不知道设计一个向后兼容的标准意味着什么。我对代码进行了更多的检查,发现这确实是所有者未设置的解锁,让它发挥作用。缺少保护ilck自身数据的锁的问题通过一些技巧得到了解决,虽然很脆弱,但仍然有效。所以我会在有时间的时候发布一些详细的分析。嗨,Martin,让我对这是否有效感兴趣的一点是,虽然这不是一个灵丹妙药,但它确实可以发现一些无序锁定问题(因此可能出现死锁)。你对“不值得”有什么看法?