C语言 检查 pthread 互斥锁是锁定还是解锁(在线程锁定自身之后)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4362459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:18:29  来源:igfitidea点击:

Check to see if a pthread mutex is locked or unlocked (After a thread has locked itself)

cpthreadsdeadlockmutex

提问by ubiquibacon

I need to see if a mutex is locked or unlocked in an if statement so I check it like this...

我需要在 if 语句中查看互斥锁是锁定还是解锁,所以我像这样检查它...

if(mutex[id] != 2){
    /* do stuff */
}

but when I check it gcc gives me the following error:

但是当我检查它时,gcc 给了我以下错误:

error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')

error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')

So how can I check to see if the mutex is locked or not?

那么如何检查互斥锁是否被锁定呢?

EDIT:

编辑:

A key component to my problem is that my threads (by design) lock themselves right AFTER passing control to another thread. So when thread A passes control to thread B thread A is locked, thread B does some stuff, then when thread B is done it will unlock thread A.

我的问题的一个关键组成部分是我的线程(按设计)在将控制权传递给另一个线程后立即锁定自己。因此,当线程 A 将控制权传递给线程 B 时,线程 A 被锁定,线程 B 执行某些操作,然后当线程 B 完成时,它将解锁线程 A。

The problem with this is that if thread B attempts to unlock thread A and thread A has not yet completed locking itself then the call to unlock is lost and thread A remains locked which causes a dead lock.

这样做的问题是,如果线程 B 尝试解锁线程 A 而线程 A 还没有完成对自身的锁定,那么解锁的调用就会丢失并且线程 A 保持锁定状态,这会导致死锁。

UPDATE:

更新:

I remade my program taking caf's suggestion but I am still running into problems. I have molded my program into the structure caf provided the best I can but I cannot even tell what is causing the dead lock now... I have created a new question hereseeking help with my code.

我根据 caf 的建议重新制作了我的程序,但我仍然遇到问题。我已经将我的程序塑造成我所能提供的最好的结构 caf,但我现在什至无法说出导致死锁的原因......我在这里创建了一个新问题寻求有关我的代码的帮助。

Below is a runnable version of caf's suggestion. I made a small reordering in the function for thread a, without which both thread a and thread b would have been locked upon their creation, waiting for a condition that could never change.

下面是 caf 建议的可运行版本。我在线程 a 的函数中做了一个小的重新排序,否则线程 a 和线程 b 在创建时都会被锁定,等待一个永远不会改变的条件。

#include <pthread.h>

int run_a = 0;
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER;

int run_b = 0;
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;

void *a(void *);
void *b(void *);

int main(){
    int status;
    pthread_t thread_a;
    pthread_t thread_b;

    pthread_create(&thread_a, NULL, a, (void *)0);
    pthread_create(&thread_b, NULL, b, (void *)0);

    pthread_join(thread_a, (void **)&status);
    pthread_join(thread_b, (void **)&status);

}

/* thread A */
void *a(void *i){
    while (1) {
        printf("thread A is running\n");
        sleep(1);

        /* unlock thread B */
        pthread_mutex_lock(&lock_b);
            run_b = 1;
            pthread_cond_signal(&cond_b);
        pthread_mutex_unlock(&lock_b);

        /* wait for thread A to be runnable */
        pthread_mutex_lock(&lock_a);
            while (!run_a)
                pthread_cond_wait(&cond_a, &lock_a);
            run_a = 0;
        pthread_mutex_unlock(&lock_a);      
    }
}

/* thread B */
void *b(void *i){
    while (1) {
        /* wait for thread B to be runnable */
        pthread_mutex_lock(&lock_b);
            while (!run_b)
                pthread_cond_wait(&cond_b, &lock_b);
            run_b = 0;
        pthread_mutex_unlock(&lock_b);

        printf("thread B is running\n");
        sleep(1);

        /* unlock thread A */
        pthread_mutex_lock(&lock_a);
            run_a = 1;
            pthread_cond_signal(&cond_a);
        pthread_mutex_unlock(&lock_a);
    }
}

回答by asveikau

You can use pthread_mutex_trylock. If that succeeds, the mutex was unclaimed and you now own it (so you should release it and return "unheld", in your case). Otherwise, someone is holding it.

您可以使用pthread_mutex_trylock. 如果成功,则互斥锁无人认领,您现在拥有它(因此您应该释放它并返回“未持有”,在您的情况下)。否则,有人拿着它。

I have to stress though that "check to see if a mutex is unclaimed" is a very bad idea. There are inherent race conditions in this kind of thinking. If such a function tells you at time tthat the lock is unheld, that says absolutely nothing about whether or not some other thread acquired the lock at t+1.

我必须强调,“检查互斥锁是否无人认领”是一个非常糟糕的主意。这种思维存在固有的竞争条件。如果这样的函数在某个时间告诉您t该锁未持有,则绝对不能说明其他线程是否在 处获得了该锁t+1

In case this is better illustrated with a code example, consider:

如果使用代码示例更好地说明这一点,请考虑:

bool held = is_lock_held();

if (!held)
{
  // What exactly can you conclude here?  Pretty much nothing.
  // It was unheld at some point in the past but it might be held
  // by the time you got to this point, or by the time you do your
  // next instruction...
}

回答by caf

Mutexes are not the right primitive for the scheme that you want to implement. You should be using condition variables:

互斥体不是您要实现的方案的正确原语。您应该使用条件变量

int run_thread_a = 0;
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER;

int run_thread_b = 0;
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER;

/* thread A */
while (1) {
    /* Wait for Thread A to be runnable */
    pthread_mutex_lock(&run_lock_a);
    while (!run_thread_a)
        pthread_cond_wait(&run_cond_a, &run_lock_a);
    run_thread_a = 0;
    pthread_mutex_unlock(&run_lock_a);

    /* Do some work */

    /* Now wake thread B */
    pthread_mutex_lock(&run_lock_b);
    run_thread_b = 1;
    pthread_cond_signal(&run_cond_b);
    pthread_mutex_unlock(&run_lock_b);
}

/* thread B */
while (1) {
    /* Wait for Thread B to be runnable */
    pthread_mutex_lock(&run_lock_b);
    while (!run_thread_b)
        pthread_cond_wait(&run_cond_b, &run_lock_b);
    run_thread_b = 0;
    pthread_mutex_unlock(&run_lock_b);

    /* Do some work */

    /* Now wake thread A */
    pthread_mutex_lock(&run_lock_a);
    run_thread_a = 1;
    pthread_cond_signal(&run_cond_a);
    pthread_mutex_unlock(&run_lock_a);
}

Each thread will block in pthread_cond_wait()until the other thread signals it to wake up. This will not deadlock.

每个线程都会阻塞,pthread_cond_wait()直到另一个线程通知它唤醒。这不会死锁。

It can easily be extended to many threads, by allocating one int, pthread_cond_tand pthread_mutex_tper thread.

通过为每个线程分配一个int,pthread_cond_tpthread_mutex_t每个线程,它可以轻松扩展到多个线程。

回答by Huang F. Lei

You can't compare a pthread_mutex_t with a int.

您无法将 pthread_mutex_t 与 int 进行比较。

You can use

您可以使用

int pthread_mutex_trylock(pthread_mutex_t *mutex);

to check that.

检查那个。