【问题标题】:Is mutex locked by me already?互斥锁已经被我锁定了吗?
【发布时间】:2020-02-27 12:59:09
【问题描述】:

一个函数正在对必须通过互斥锁防止并发线程的变量执行操作。
此函数的调用者锁定一个互斥体,执行其他操作并调用此函数。

现在出现了需要从另一段代码调用此函数的情况。
当然,这段代码也可以锁定互斥锁,但我想也许该函数可以查看它是否必须锁定互斥锁。

我需要一个函数来告诉我当前线程是否锁定了互斥锁。然后该功能可以在没有锁定的情况下继续。否则它会锁定。

int need_to_lock = !my_thread_has_locked_the_mutex(&mutex);

if (need_to_lock)
    mutex_lock(&mutex);

access variables;

if (need_to_lock)
    mutex_unlock(&mutex);

my_thread_has_locked_the_mutex 是否存在?我找不到任何东西。

编辑到 cmets

我不知道递归互斥锁。他们似乎按照我的想法行事。
我现在使用的是一个非递归互斥锁,如果从同一个线程锁定两次,就会阻塞。

【问题讨论】:

  • 你可以使用recursive mutex
  • 如果你在同一个线程中,再次锁定没有害处(参见:“递归互斥锁”)。如果另一个线程已锁定,那么您的线程将等待锁定,这正是互斥锁的要点。您提出的检查-然后-执行的情况是一种竞争条件,因为另一个线程可能会在检查和操作之间锁定/解锁。
  • ... 这个通用的习惯用法很常见:不是在对跨线程依赖做某事之前进行检查,而是简单地尝试(使用支持这一点的 API)并在 之后进行检查 i> 是否有效。当然,细节会有所不同,包括尝试是否会阻塞,但一般模式基本上适用于所有同步操作和许多原子操作。实际上,即使对于单线程代码,这也是一个标准的习惯用法:看看有多少函数的返回值传达了包括函数是成功还是失败的信息。
  • “因为另一个线程可以在检查和操作之间锁定/解锁” - 是的,另一个线程可以在此时锁定,但这不会造成伤害,因为我的函数会按照互斥锁的预期等待。唯一的一点是,如果我的线程已经有了互斥锁,那么我就不必再次锁定它了。

标签: c mutex


【解决方案1】:

为什么不直接使用递归互斥锁呢?递归互斥锁与常规互斥锁基本相似,但可以由单个线程多次锁定(即递归)。

在某些库中,互斥锁默认是递归的。使用 C pthreads,您需要通过适当地初始化互斥锁来选择递归互斥锁:

pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(mutex, &attr);

另一种方法是将您的函数拆分为两种变体:一种应在持有互斥锁的情况下调用,另一种应在不持有互斥锁的情况下调用。通常的命名约定是将_locked 附加到前者,或将_unlocked 附加到后者。解锁函数只是锁定互斥体,然后调用锁定函数,因此这里不会有任何真正的代码重复。

【讨论】:

    猜你喜欢
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    • 2018-05-23
    相关资源
    最近更新 更多