1. 线程同步问题
伴随着多线程的使用,同步的问题是不可避免的出现,这是为什么呢?

首先我们看以下的例子:
全局变量g_nData在主线程及子线程中都有分别加10万次,结果会是怎样呢?

#include <tchar.h>
#include <iostream>
#include <thread>using namespace std;int g_nData = 0;//回调函数中对全局变量g_nData做加法操作
//子线程中加10万次
void foo() {for (int i = 0; i < 100000; i++) {g_nData++;}}int _tmain(int argc, _TCHAR* argv[])
{//定义一个子线程的对象 回调函数为foo()std::thread t(foo);//主线程中全局变量g_nData也加10万次for (int i = 0; i < 100000; i++) {g_nData++;}t.join();std::cout << g_nData << std::endl;return 0;
}

运行结果:

看到结果一脸懵逼,怎么着也不应该是119797呀!按想法应该要跑20万次呀!再跑一次看看。

值又不一样了,这就是多线程带来的同步的问题。

2. 线程同步问题的产生原因
分析一下问题:我们所写的C++语言属于高级语言,电脑在运行时会想将其转为低级语言即汇编语言。高级语言(c/c++)–>低级语言(汇编代码)
(1)在子线程的g_nData++处设置断点并进行反汇编

(2)一行g_nData++的高级语言反汇编后看到有三句

释义:

/*
00DB42F3  mov         eax,dword ptr [g_nData (0DBF380h)]  寄存器eax=内存中g_nData数值g_nData++;
00DB42F8  add         eax,1                               寄存器eax++
00DB42FB  mov         dword ptr [g_nData (0DBF380h)],eax  内存中g_nData数值=寄存器eax
*/

查看反汇编代码的方法:

(3) 同时主线程g_nData++处设置断点并进行反汇编,并与子线程的汇编代码放在一起比较:

子线程
00DB42F3  mov         eax,dword ptr [g_nData (0DBF380h)]  寄存器eax=内存中g_nData数值
00DB42F8  add         eax,1                               寄存器eax++
00DB42FB  mov         dword ptr [g_nData (0DBF380h)],eax  内存中g_nData数值=寄存器eax主线程:
005A48D9  mov         eax,dword ptr [g_nData (0DBF380h)]
005A48DE  add         eax,1
005A48E1  mov         dword ptr [g_nData (0DBF380h)],eax

子线程和主线程同时运行,其实质是利用时间片即交替20ms分别执行,一个执行完就挂起执行另一个线程,那么就有一种可能,一个线程中三行代码没执行完,但是时间到了,转而执行另一个线程。

(4)通俗易懂的举个例子:
子线程在20ms期间执行5000次,时间到的时候刚执行完以下代码:005A48E1 mov dword ptr [g_nData (0DBF380h)],eax,并没有从寄存器中将值传递给内存,就转而执行主线程。
主线程接着执行了6000次,时间到了之后又传递给子线程,诡异的事情就在此时发生,因为刚才从子线程转到主线程的时候,下一步就是005A48E1 mov dword ptr [g_nData (0DBF380h)],eax,这个时候系统就会让寄存器的值变为5000,紧接着运行,主线程的6000次就白跑了。

3. 线程同步问题的解决方法
为了解决上面的问题,我们可以怎么去修改代码呢?
方法很多,其中一种就是将t.join();提前,这样就可以等前面子线程运行结束才会执行下面的10万次的加法,这样就可以实现结果为20万次。

int _tmain(int argc, _TCHAR* argv[])
{//定义一个子线程的对象 回调函数为foo()std::thread t(foo);t.join();//主线程中全局变量g_nData也加10万次for (int i = 0; i < 100000; i++) {g_nData++;}std::cout << g_nData << std::endl;return 0;
}


但是这种方法将同步运行变成了先后的运行,并未实现并发的要求,是伪并发,下篇我们将会讨论如何解决这些问题。

4. 学习视频地址:线程同步问题的产生原因

C++新特性28_线程同步问题的产生原因(高级语言转为低级语言执行,时间片交替运行多线程中代码,代码切换过程中出现的问题)相关推荐

  1. Java高并发革命!JDK19新特性——虚拟线程(Virtual Threads)

    介绍 虚拟线程具有和 Go 语言的 goroutines 和 Erlang 语言的进程类似的实现方式,它们是用户模式(user-mode)线程的一种形式. 在过去 Java 中常常使用线程池来进行平台 ...

  2. 线程同步有几种方法_架构师面试必问的多线程状态切换及常用方法

    架构师面试必问的多线程状态切换及常用方法 一.问题背景 Java架构师面试中,多线程状态切换及常用方法几乎是必问的,要掌握创建多线程的方式和方法. 二.创建多线程的几种方式 2.1方式一继承Threa ...

  3. java1.7线程暂停_Java实现多线程断点下载实例代码(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

  4. 线程基础:JDK1.5+(9)——线程新特性(中)

    (接上文<线程基础:JDK1.5+(8)--线程新特性(上)>) 3.工作在多线程环境下的"计数器": 从这个小节开始,我们将以一个"赛跑"的例子, ...

  5. 解析JVM线程同步机制

    http://blog.csdn.net/thl789/article/details/566494 对多线程的支持一般是在OS级的,而Java将其做在了语言级别,这其中最吸引人的莫过于Java对线程 ...

  6. 多线程下的进程同步(线程同步问题总结篇)

    之前写过两篇关于线程同步问题的文章(一,二),这篇中将对相关话题进行总结,本文中也对.NET 4.0中新增的一些同步机制进行了介绍. 首先需要说明的是为什么需要线程功能同步.MSDN中有这样一段话很好 ...

  7. Java春招面试复习:JDK 5-15都有哪些经典新特性

    前言 JDK 15发布啦~ 我们一起回顾JDK 5-15 的新特性吧,大家一起学习哈~ 本文已经收录到github https://github.com/whx123/JavaHome 公众号:捡田螺 ...

  8. Android5.0,6.0,7.0,8.0新特性整理

    背景 Android5.0(Android Lollipop)是谷歌公司2014年10月发布的全新安卓系统,至今已经两年多.然而由于国产手机对安卓ROM的深度定制或修改,以及手机厂商.芯片制造商.运营 ...

  9. Android5.0,6.0,7.0新特性整理

    背景 Android5.0(Android Lollipop)是谷歌公司2014年10月发布的全新安卓系统,至今已经两年多.然而由于国产手机对安卓ROM的深度定制或修改,以及手机厂商.芯片制造商.运营 ...

  10. Android5.0 6.0 7.0新特性

    原文链接:http://blog.csdn.net/haovip123/article/details/54618642 背景 Android5.0(Android Lollipop)是谷歌公司201 ...

最新文章

  1. 联想拯救者15isk装win10系统_笔记本电脑触摸板操作手势合集以拯救者Win10系统为例...
  2. mysql5.7.11无法启动_mysql 5.7.11 启动报错
  3. stm32qspi内存映射_STM32F7-discovery QSPI接口使用心得
  4. STM32 电机教程 8 - 步进电机开环电流控制
  5. 苏州大学计算机考研复试经验,苏州大学计算机考研复试经验总结.docx
  6. python字符复制函数是啥_Python最全的字符和字符串函数,直接复制到IDLE或另存为py可以运行...
  7. oracle进程内存不足1046552,ora-04030 进程内存不足解决方案
  8. thinkphp 调用wsdl接口实例化SoapClient抛出异常
  9. 机器学习实战——k-邻近算法:约会网站
  10. 人工智能笔记之专业选修课4.1.5 - 博弈论 11.贝叶斯博弈场景-拍卖,合作博弈论
  11. Java实现第九届蓝桥杯分数
  12. 轻松绕过PayPal双重认证
  13. 计算机入门在线阅读,计算机应用基础教程(Windows 7+Office 2010)
  14. linux who 时间,linux命令之who、w、whoami
  15. CSS 文本超出溢出显示省略号...
  16. 如何设置修改网页中滚动条
  17. 用Keras解决机器学习问题!
  18. Redis之sql缓存
  19. 决战奶酪之巅,剑指Big Cheeze
  20. Ora2Pg 工具介绍

热门文章

  1. java实现接口必须实现所有方法吗_我们是否必须在实现Java接口的类中实现所有方法?...
  2. typescript中this报错
  3. 那些年你错过的SOA
  4. FPGA基础入门【10】开发板Ethernet PHY局域网配置
  5. 如何用代码实现发送qq邮件(详细代码)
  6. 行人跟踪之身份识别(一)
  7. excel公式不执行。原因是设置问题:公式->计算选项->手动
  8. 计算机怎么显示正确,电脑显示器怎么正确设置
  9. reg类型变量综合电路_Verilog中 reg和wire 用法和区别以及always和assign的区别
  10. linux终端文件名前特殊符号,Linux特殊符号大全