示例考虑将有两个线程 T1 和 T2
你怎么发现它们?
如果多个线程可以访问相同的变量/资源/内存位置,并且至少线程正在更改变量/资源/内存位置的值,则可能发生 Race Condition 。因为如果一个线程正在改变变量/资源/内存位置的值而另一个线程试图读取相同的值,那么它将不会获得更新的值。
注意 :如果所有线程只是读取*变量/资源/内存位置,*则不会发生 Race Condition 。
示例:程序受 Race Race 影响
#include <stdio.h>
#include <pthread.h>
int x= 0;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
我屏幕上的输出是:
Point 1 >> X is: 0
Point 2 >> X is: 9925047
你的输出会有所不同。但肯定不会是 20,000,000。由于两个线程执行相同的循环并具有全局变量 int x;
for ( i = 0; i < 10000000; i++ )
{
x++;
}
所以 x
在线 Point 2 >> X is: 9925047
的最终值应该是 20,000,000。但事实并非如此。
在读取 x 和写回 x 之间的时间内,x 的状态可以被另一个线程更改。
假设一个线程检索 x 的值,但尚未存储它。另一个线程也可以检索相同的 x 值(因为还没有线程改变它),然后它们都将相同的值(x + 1)存储回 x!
例:
线程 1:读取 x,值为 7
线程 1:将 x 加 1,值现为 8
线程 2:读取 x,值为 7
线程 1:在 x 中存储 8
线程 2:将 x 加 1,值现为 8
线程 2:在 x 中存储 8
你怎么处理它们?
通过在访问共享资源或互斥的代码之前采用某种锁定机制,可以避免竞争条件。
以下是修改后的程序:
示例:已解决竞争条件问题
#include <stdio.h>
#include <pthread.h>
int x= 0;
//Create mutex
pthread_mutex_t test_mutex;
void* fun(void* in)
{
int i;
for ( i = 0; i < 10000000; i++ )
{
//Lock mutex before going to change variable
pthread_mutex_lock(&test_mutex);
x++;
//Unlock mutex after changing the variable
pthread_mutex_unlock(&test_mutex);
}
}
int main()
{
pthread_t t1, t2;
printf("Point 1 >> X is: %d\n", x);
//Initlize mutex
pthread_mutex_init(&test_mutex, NULL);
pthread_create(&t1, NULL, fun, NULL);
pthread_create(&t2, NULL, fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
//Destroy mutex after use
pthread_mutex_destroy(&test_mutex);
printf("Point 2 >> X is: %d\n", x);
return 0;
}
以下是输出:
Point 1 >> X is: 0
Point 2 >> X is: 20000000
在这里,答案每次都是 20,000,000。
注意 :修改后的程序没有竞争条件错误,执行起来需要很长时间。因为 mutex
锁定和解锁有负担。