Amm*_*izi 1 c multithreading mutex locking pthreads
根据手册页https://linux.die.net/man/3/pthread_mutex_lock
互斥锁引用的互斥锁对象应通过调用 pthread_mutex_lock() 锁定。如果互斥锁已被锁定,则调用线程应阻塞,直到互斥锁可用。
我有一个带线程的程序。这是程序流程:
pthread_mutex_lock一个循环内。pthread_mutex_unlock,线程应该突然获得锁。问题是,在第 3 点,线程不会在主进程释放锁后立即获得锁。主进程pthread_mutex_lock在下一个循环周期(在第 4 点)调用时首先获得它。
如何处理这种情况?
如何让线程在主进程释放锁后立即获得锁?
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
void *
my_thread(void *p)
{
  (void)p;
  while (1) {
    pthread_mutex_lock(&my_mutex);
    printf("The thread is holding the lock...\n");
    sleep(1);
    pthread_mutex_unlock(&my_mutex);
  }
}
int
main()
{
  pthread_t t;
  pthread_create(&t, NULL, my_thread, NULL);
  pthread_detach(t);
  while (1) {
    pthread_mutex_lock(&my_mutex);
    printf("The main process is holding the lock...\n");
    sleep(1);
    pthread_mutex_unlock(&my_mutex);
  }
}
gcc test.c -o test -lpthread
./test
The main process is holding the lock...
The thread is holding the lock...
The main process is holding the lock...
The thread is holding the lock...
The main process is holding the lock...
The thread is holding the lock...
The main process is holding the lock...
...
The main process is holding the lock...
The main process is holding the lock...
The main process is holding the lock...
The main process is holding the lock...
The main process is holding the lock...
The main process is holding the lock...
The main process is holding the lock...
...
main   -> [1] call lock (get the lock)
thread -> [2] call lock (waiting for main to unlock)
main   -> [3] call unlock
thread -> [4] (still does not get the lock from [2], why? even though it has been unlocked?)
main   -> [5] lock (get the lock again)
thread -> [6] (still does not get the lock from [2])
main   -> [7] call unlock
thread -> [8] (still does not get the lock from [2], why? even though it has been unlocked?)
main   -> [9] lock (get the lock again)
... and so on ...
pthread_mutex_lock 不保证锁请求的顺序。
pthread_mutex_lock保证它会锁定,直到互斥锁可用。这并不意味着每个 lock() 调用都会进入一个队列并保证接下来获得互斥锁。这仅意味着其他人不会同时拥有锁。
如果您需要某个顺序,则可以选择使用条件变量。这样,您可以将标志设置为下一个应该获得互斥锁的成员。然后您可以等待互斥锁,直到该值符合预期。请参阅https://linux.die.net/man/3/pthread_cond_wait。
或者,如果您的示例无论如何都在其中睡眠,那么您可以在 unlock() 调用后移动睡眠。虽然严格来说这不是保证,但它绝对可以为简单测试提供帮助。不过,我不建议将这种方法用于更严重/更复杂的事情。
编辑:正如 Shawn 正确添加的那样,如果您不关心它是哪个其他线程,您还可以使用pthread_yield( 1 ) 来允许另一个线程获取互斥锁。sched_yield(2)中描述了一些与屈服的复杂性。
PS:我会发表评论,但我的代表现在已经足够高了:)