我一直在学习多线程应用程序,尤其是如何使用互斥体来防止竞争条件。然而,在编写一些代码时,我在我的代码中发现了一个竞争条件(使用 valgrind
中的 helgrind
工具),我相信一个线程中的执行可能会在解锁并在返回之前。
如果我们采用下面的示例代码,在互斥锁解锁和返回语句之间是否可能存在竞争条件?如果是这样,我们如何解决这个问题?(除了要求调用者传入某种缓冲区并返回一个常量值,如 0
)
#include <pthread.h>
int x = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
doSomething()
{
pthread_mutex_lock(&mutex);
++x;
pthread_mutex_unlock(&mutex);
/* <-- Race Condition? */
return x;
}
void *t2()
{
doSomething();
}
main()
{
pthread_t thread;
pthread_t_create(&thread, NULL);
doSomething();
pthread_join(thread, NULL);
return 0;
}
注意:我明白在上面的例子中,返回 'x' 是没有用的,因为 x 是全局的。但是,在“x”对于库函数而言需要全局但又不能向用户公开的库中,返回值变得很重要。
最佳答案
这是您当前代码中的事件序列:
- 打开锁。
- 读取共享的
x
变量。 - 返回您读取的值。
x
的读取完全不 protected 。
你需要做的是
- 读取共享的
x
变量。 - 打开锁。
- 返回您读取的值。
这样读就受到了锁的保护。为此,在解锁之前将 x
的值存储到一个非共享(本地)变量,并将其用作返回值:
int retval = x;
pthread_mutex_unlock(&mutex);
return retval;
关于互斥锁解锁和从函数返回之间是否会出现竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41153505/