网络编程(37)—— 线程访问的临界区是怎么形成的

本文通过一个具体的多线程编程示例,探讨了临界区形成的原因及其过程。通过对示例代码的分析,解释了为何在多线程环境下对共享资源的操作可能导致预期之外的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        本文主要讨论多线程访问中临界区形成的问题,从本质上讲,临界区的形成是在多线程中,不同的线程访问和操作同一片内存,而形成的。在具体分析之前,我们先来看一个多线程的列子:
#include<stdio.h>
#include<pthread.h>
int num=0;
void* pthread_main1()
{
    int i=0;
    for(i=0;i<1000000000;i++)
    {
         num++;
    }
}

void* pthread_main2()
{
    int i=0;
    for(i=0;i<1000000000;i++)
    {
        num--;
    } 
}
int main()
{
    int i=0;
    pthread_t pid[2];
    pthread_create((void*)&(pid[0]),NULL,(void*)pthread_main1,NULL);
    pthread_create((void*)&(pid[1]),NULL,(void*)pthread_main2,NULL);
    for(i=0;i<2;i++)
    {
        pthread_join(pid[i],NULL);
    }
    printf("%d\n",num);
    return 0;
}


        我们分别定义了两个线程函数pthread_main1和pthread_main2,在函数中分别对全局变量num进行++和--操作,且操作次数一致,num的初始值是0,最后在主函数中打印结果时,num的值会不会变成0呢?
       答案肯定是不会,因为有临界区的存在,我们先来看下运行的结果:
[Hyman@Hyman-PC multithread]$ gcc ts3.c -D_REENTRANT -lpthread
[Hyman@Hyman-PC multithread]$ ./a.out 
-507431
[Hyman@Hyman-PC multithread]$ 

        下面我们就根据这个例子来分析下临界区的产生过程。首先,我们先分析下在线程函数中num++和num--过程中,因为++和--在操作过程中表现是一样的,所以以++为例进行分析:
 第一步,num是存放在内存的全局数据段中的,++操作时操作系统先把num的值存放到CPU的寄存器中。
第二步,CPU负责计算,将num的值加1.
第三步,操作系统又把寄存器已经加1的值写会到num所在的内存中。
        我们期望的方式是在线程1中上述三步全部完成后,再执行线程2中num--的操作,这样最后得到的结果就会是期望值0。
但事实时,也许执行到第一步或者第二步的时候就开始执行num--的操作了。比如:num的初始值是0,当执行到num++的第二步时,num将要被执行第三步变成1之前,线程2开始执行num--的代码,而且执行完成了num--的三个步骤,此时num变成了-1,而这时开始执行num++的第三步,将寄存器中的1写入到了num的内存中,显然现在num又变成1。在分别执行num++和num--之后,num变成了1,显然这并不是我们期望的。
        这就是临界区的形成,它不是变量num,而是一段代码num++和num--。让我们再总结一下,它的形成条件:
1、多个线程同时访问一片内存,并企图修改这片内存(在例子里就是num所在的内存)。

2、修改片内存是通过多步骤的操作完成的(实际上这是必然存在的条件,因为我们只要想修改这片内存的内容,操作系统就会分步骤完成,不会一蹴而就)。


Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
Git clone git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL37



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值