理解计算机系统_并发编程(6)_线程(三):线程内存模型和同步问题

前言
       

        以<深入理解计算机系统>(以下称“本书”)内容为基础,对程序的整个过程进行梳理。本书内容对整个计算机系统做了系统性导引,每部分内容都是单独的一门课.学习深度根据自己需要来定

引入

        接续上一篇理解计算机系统_并发编程(5)_基于线程的并发(二):线程api和基于线程的并发服务器-CSDN博客

多线程程序中的共享变量

        本书P696:从程序员的角度来看,线程很有吸引力的一个方面是多个线程很容易共享相同的程序变量.为了让我们对共享的讨论具体化,我们将使用图12-15中的程序作为运行示例.示例程序由一个创建了两个对等线程的主线程组成.主线程传递一个唯一的ID给每个对等线程,每个对等线程利用这个ID输出一条个性化的信息,以及调用该线程例程的总次数.---黑体字是原话,下面有代码和说明

线程内存模型

        参见理解计算机系统_并发编程(4)_基于线程的并发(一):线程基础-CSDN博客,线程模型和进程类似.

代码sharing.c

共享变量的解读

        本书内容讲得很仔细.简单地说,能理解C语言中的几类变量,就能理解共享变量,因为与之差不多.共享变量只有几种形式:全局变量局部静态变量,及main()函数里代码前声明的局部变量.线程函数thread中的局部变量(myid)是不共享的,因为执行完毕后会释放内存空间.

        共享变量的定义:我们说一个变量v是共享的,当且仅当他的一个实例被一个以上的线程引用.例如,示例程序中的变量cnt就是共享的,因为他只有一个运行时实例,并且这个实例被两个对等线程引用.同时,myid不是共享的,因为他的两个实例中每一个都只被一个线程引用.---黑体字是原话

        ---解读:一个实例,如果被多个线程引用,即为共享,否则(一个实例只有一个线程引用),则不共享. 

        然而,认识到像msgs这样的本地自动变量也能被共享是很重要的.---黑体字是原话       

        ---解读:这里的说法有一点小问题,函数中的本地变量不能共享.但是main()函数中的本地变量可以,在代码第16行,他是通过全局变量ptr来实现共享的.

本书代码小错误

        第24行的错误,把传入的指针(i的地址)强制转换成整型数值,是不对的

//以下代码是错的
int myid=(int)vargp;

        修改如下

int myid=*((int*)vargp);    //推荐,和上一段代码保持一致
int myid=(int)(*vargp);     //也可能会出问题,不推荐        

        这里注意的知识点:将void* 通用指针强制转换成其他指针时必须先指明指针类型. 第二种不推荐写法,不知道*vargp会被计算机怎么理解,32位int型?64位long型?为了不冒指针越界的风险,凡是遇到这种情况统一写成第一种.

 同步问题

        本书P698代码badcnt.c,引入了同步错误这个概念.

        笔者对同步错误做个简单理解:有两个线程A和B对共享数据share_data操作,当线程A修改共享数据share_data后未写回的时候,被线程B中断,则实际上线程A的操作未成功,当线程B再次切换回线程A时,结果已被更改.

        /*就好像:你做了个word文档但是没点保存,下次打开时写好的东西没了*/.

产生同步问题代码

        线程函数thread,本书P699第36行~第44行

void *thread(void *vargp)
{
    long i,niters=*((long*)vargp);

    for(i=0;i<niters;i++)
        cnt++;

    return NULL;
}

        其中和共享数据有关的在for循环里,就是这一句:cnt++;

        本书后面讲了许多,还引出了汇编代码.关键是写得比较乱.就不细说了.

        其实理解起来很简单,如果第一个线程执行了cnt++,但并没有把cnt的结果保存下来(写到某个寄存器中),这时第二个线程中断了第一个线程去执行他的代码,当CPU再次发生中断回来执行第一个线程时,cnt的值已不是预期的那个值.

        对此本书有总结:这里有个关键点:一般而言,你没有办法预测操作系统是否将为你的线程选择一个正确的顺序.操作系统不会知道被他中断的那个指令是否对结果产生影响.

小结

        简单分析了线程共享变量和同步问题的原因

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重庆彭枫

你的鼓励是我创作的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值