示例考虑将有两个线程 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 锁定和解锁有负担。