一组并发线程运行在一个进程的上下文中,每个线程都有它自己独立的线程上下文,例如:栈、程序计数器、线程ID、条件码等,每个线程和其它的线程一起共享除此之外的进程上下文的剩余部分,包括整个用户的虚拟地址空间,当然也共享同样的打开的文件的集合。,这里有一点要特别注意,就是寄存器是从不共享的,而虚拟存储器总是共享的。

有了共享就要防止在对共享变量进行操作的过程中得到一个不可知的值,在Linux内核中有个原子类型与原子操作这么个概念,因为用户态下没有这么一个原子操作存在,那么在我们用户态下就需要要对操作这个共享变量的线程进行同步。为什么要进行同步呢?
因为假设我们在一个程序中有一个全局变量cnt,初始值为0,接下去我们创建了两个线程,完成的功能都是在一个循环中对这个变量进行+1操作,想象一下在这两个线程操作完成后会出现什么状况。

点击(此处)折叠或打开

  1. void *thread(void* value)
  2. {
  3. int max = *((int*)value)
  4. for(int i=0;imax;i++)
  5. {
  6. cnt++;
  7. }
  8. return NULL;
  9. }

假设我们这里的max为10000,那么我们想要得到的结果的结果当然是20000,可是在执行之后结果并不是我们所期望的20000,而是一个小于20000的值。为什么会出现这个现象呢?

这里就是我们为什么需要对线程进行同步了。
因为在C语言的层面来说,cnt++就是一条语句,实际上我们在心里默认把它当作了一个原子操作,事实上,就这么一条操作语句,在汇编代码中是分三步执行的:
1)、将这个值从内存中取出来,放入一个寄存器中;
2)、将寄存器中的值进行+1操作;
3)、将寄存器中的值放入内存中去。
因为对与多线程来说我们不知道何时会执行哪个线程,所以执行的顺序是不可知的。我们所想的是先让一边执行完,然后再开始执行另外一边。
现在我们不妨将这个问题极端化,也就是两线程交叉执行,假设左边的执行线程为A,右边为B,假设A先执行,A从内存中取出cnt的值,那么现在在R1里的值为0,接下去,A线程被B线程打断,A停止执行,B开始执行,B又从内存中取出cnt的值,现在在R2中的值也为0。然后又轮到A执行,进行加1操作,则R1为1,接下去轮到B执行,进行加1操作,则R2为1。然后A将值写回到内存中,B也将值写回到内存中。这次我们知道内存中的值为1而并非我们所期望的2。
那么怎么能让它进行正确的执行顺序呢?同步,可以用加锁来完成同步操作。

点击(此处)折叠或打开

  1. for(int i=0;imax;i++)
  2. {
  3. P(&mutex);
  4. cnt++;
  5. V(&mutex);
  6. }

在对cnt加1的操作时,对这个操作加锁,这就意味着当下只有这一个线程执行这个操作,其它的线程都得等在外面,等这个线程解锁出来,其他的线程才可以有机会进去。

加锁之后我们再来看看上面的那张图的执行过程,也假设是在一个极端的情况:
A先加锁,然后完成那三个步骤(因为此时只有它一个线程有操作的权限),解锁;现在内存中的值为1,A加锁,然后一样完成三个步骤,解锁;现在内存中的值为2。与所期望的相同。当然了,对于加锁的问题还要防止出现死锁现象,这里就不讨论了。

多线程中的使用共享变量的问题相关推荐

  1. java闭合数据_java多线程中线程封闭详解

    线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的 ...

  2. 多线程中的应用之队列(queue)

    队列queue 多应用在多线程中,对于多线程访问共享变量时,队列queue是线程安全的. 从queue队列的实现来看,队列使用了1个线程互斥锁(pthread.Lock()),以及3个条件标量(pth ...

  3. 单例模式在多线程中的安全性研究

    概述 关于一般单例模式的创建和分析在我的另一篇博客<Java设计模式--单件模式>中有详细说明.只是在上篇博客中的单例是针对于单线程的操作,而对于多线程却并不适用,本文就从单例模式与多线程 ...

  4. java多线程同步与死锁_浅析Java多线程中的同步和死锁

    Value Engineering 1基于Java的多线程 多线程是实现并发机制的一种有效手段,它允许编程语言在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立,且与进程一样拥有独立 ...

  5. 【Linux】多线程中使用fork()

    (最核心的东西我在下面用红色字体标出来了,理解了那块,这些东西都是就理解了!) 在本篇文章开始之前,需要大家先了解线程和进程,这位大哥讲的言简意赅:进程和线程的主要区别(总结)_kuangsongha ...

  6. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  7. 了解多线程中的yield

    2019独角兽企业重金招聘Python工程师标准>>> 最近在学习多线程这一块,发现里面有好多让人产生误区的地方,今天我来分析下java多线程中的yield功能,希望其他朋友也可以从 ...

  8. 解决DataGridView在多线程中无法显示滚动条的问题

    解决DataGridView在多线程中无法显示滚动条的问题 参考文章: (1)解决DataGridView在多线程中无法显示滚动条的问题 (2)https://www.cnblogs.com/roph ...

  9. VMware 虚拟化编程(8) — 多线程中的 VixDiskLib

    目录 目录 前文列表 多线程注意事项 多线程中的 VixDiskLib 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化 ...

最新文章

  1. 老生常谈:工厂模式兄弟姐妹
  2. mysql connector c编程_MySQL数据库之MySQL Connector 编程
  3. html列表变成三个一行,HTML列表仅限第一行缩进
  4. python# 完成“剪刀石头布游戏”:
  5. 支付宝 android 2.3,app被拒记录-2.3-包含支付宝
  6. 部署FIM 2010 R2—1先决条件准备
  7. Linux下如何查找软件安装路径(mysql为例)
  8. 装了python3但在cmd里不识别,Pip无法识别安装命令(Windows 7,Python 3.3)
  9. oracle11g的用户名是什么,oracle11g默认用户名和密码
  10. 学python能做什么-学了Python都能干什么,哪个最赚钱?
  11. 怎么自学python-如何学习好Python这门课程?老男孩Python培训全套视频
  12. linux 修改时间 date
  13. NX/UG二次开发—装配—实现标准件库添加组件效果
  14. [攻防世界]crypto新手练习区Caesar
  15. 【mmdetection小目标检测教程】三、使用sahi库切分高分辨率图片,一键生成coco格式数据集
  16. 成都计算机系统维护专业中专,成都计算机应用专业中专招生简章
  17. English--vowels_双元音
  18. 信用百度公司商标信息爬取
  19. unity 360视频_如何将360视频与Unity集成
  20. python开源web项目-30 个惊艳的Python开源项目

热门文章

  1. java hello world
  2. 自学Python从哪学方面入手?
  3. 牛批了,1行python代码就可实现炫酷可视化
  4. 大数据之Python入门语法基础
  5. 美国本科计算机专业,美国本科计算机专业的最新排名介绍
  6. 添加打印机还显示脱机_win7系统电脑连接打印机后显示脱机怎么办
  7. 改变你的 KDE 桌面的外观和感觉方法介绍
  8. C语言题解:用二分法思想求解10个元素中某个元素的下标(包含函数方法)
  9. 关于报错Incorrect username or password ( access token ) Authentication failed for ‘https://gitee.com
  10. 关于学习Python的一点学习总结(15)