Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是";断言I';“我将此互斥锁保持为锁定状态”;可行吗?_C_Multithreading_Thread Safety_Pthreads_Mutex - Fatal编程技术网

C 是";断言I';“我将此互斥锁保持为锁定状态”;可行吗?

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

年,《软件清漆》的作者对新的ISO C标准草案表示失望。特别是他认为应该有一些有用的东西,比如“断言我持有这个互斥锁”函数,他声称他在《消失》中写了一个

我查了密码。它本质上是这样的:

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的访问不受任何互斥保护

因此,请按照以下事件顺序进行说明:

  • 线程A锁定互斥锁
  • 线程A解锁它
  • 线程B锁定相同的互斥锁。在锁定过程中(在 Lck_lock()),线程B在更新ilck->HOLDED但 在更新ilck->owner之前。这应该是可能的,因为 优化器和CPU出现故障
  • 线程A运行并调用Lck__断言(),断言将 如果为true,则线程A实际上不包含互斥对象

  • 在我看来,应该有一些“全局”互斥体来保护互斥体自身的数据,或者至少有一些写/读屏障。我的分析正确吗?

    我已经联系了作者。他说我的分析是有效的,并且使用memset(,0,)来取消设置“thread\t owner”,因为thread\t不是具有指定赋值运算符的透明结构。希望这在大多数平台上都有效。

    我看不到解锁代码。我认为这是正确的,重置了所有者。考虑到多线程设计的广度和复杂性以及与之相关的问题,我敢肯定,像这样的东西提供的功能,即使在所有平台上都能工作,也不值得。我觉得你链接到的博客有点可怜。他反对使用像
    \u Noreturn
    这样的关键词,并将它们与
    Noreturn
    混在一起,这表明他不知道设计一个向后兼容的标准意味着什么。我对代码进行了更多的检查,发现这确实是所有者未设置的解锁,让它发挥作用。缺少保护ilck自身数据的锁的问题通过一些技巧得到了解决,虽然很脆弱,但仍然有效。所以我会在有时间的时候发布一些详细的分析。嗨,Martin,让我对这是否有效感兴趣的一点是,虽然这不是一个灵丹妙药,但它确实可以发现一些无序锁定问题(因此可能出现死锁)。你对“不值得”有什么看法?