多线程创建其实十分简单,在windows系统下面有很多函数可以创建多线程,比如说_beginthread。我们就可以利用它为我们编写一段简单的多线程代码,

[cpp] view plaincopy
  1. #include <windows.h>
  2. #include <process.h>
  3. #include <stdio.h>
  4. unsigned int value = 0;
  5. void print(void* argv)
  6. {
  7. while(1){
  8. printf("&value = %x, value = %d\n", &value, value);
  9. value ++;
  10. Sleep(1000);
  11. }
  12. }
  13. int main()
  14. {
  15. _beginthread( print, 0, NULL );
  16. _beginthread( print, 0, NULL);
  17. while(1)
  18. Sleep(0);
  19. return 1;
  20. }

注意,在VC上面编译的时候,需要打开/MD开关。具体操作为,【project】->【setting】->【c/c++】->Category【Code Generation】->【Use run-time library】->【Debug Multithreaded】即可。

通过上面的示例,我们看到作为共享变量的value事实上是可以被所有的线程访问的。这就是线程数据同步的最大优势——方便,直接。因为线程之间除了堆栈空间不一样之外,代码段和数据段都是在一个空间里面的。所以,线程想访问公共数据,就可以访问公共数据,没有任何的限制。

当然,事物都有其两面性。这种对公共资源的访问模式也会导致一些问题。什么问题呢?我们看了就知道了。

现在假设有一个池塘,我们雇两个人来喂鱼。两个人不停地对池塘里面的鱼进行喂食。我们规定在一个人喂鱼的时候,另外一个人不需要再喂鱼,否则鱼一次喂两回就要撑死了。为此,我们安装了一个牌子作为警示。如果一个人在喂鱼,他会把牌子设置为FALSE,那么另外一个人看到这个牌子,就不会继续喂鱼了。等到这个人喂完后,他再把牌子继续设置为TRUE。

如果我们需要把这个故事写成代码,那么怎么写呢?朋友们试试看,

[cpp] view plaincopy
  1. while(1){
  2. if( flag == true){
  3. flag = false;
  4. do_give_fish_food();
  5. flag = true;
  6. }
  7. Sleep(0);
  8. }

上面的代码看上去没有问题了,但是大家看看代码的汇编代码,看看是不是存在隐患。因为还会出现两个人同时喂食的情况,

[cpp] view plaincopy
  1. 23:       while(1){
  2. 004010E8   mov         eax,1
  3. 004010ED   test        eax,eax
  4. 004010EF   je          do_action+56h (00401126)
  5. 24:           if( flag == true){
  6. 004010F1   cmp         dword ptr [flag (00433e04)],1
  7. 004010F8   jne         do_action+43h (00401113)
  8. 25:               flag = false;
  9. 004010FA   mov         dword ptr [flag (00433e04)],0
  10. 26:               do_give_fish_food();
  11. 00401104   call        @ILT+15(do_give_fish_food) (00401014)
  12. 27:               flag = true;
  13. 00401109   mov         dword ptr [flag (00433e04)],1
  14. 28:           }
  15. 29:
  16. 30:           Sleep(0);
  17. 00401113   mov         esi,esp
  18. 00401115   push        0
  19. 00401117   call        dword ptr [__imp__Sleep@4 (004361c4)]
  20. 0040111D   cmp         esi,esp
  21. 0040111F   call        __chkesp (004011e0)
  22. 31:       }
  23. 00401124   jmp         do_action+18h (004010e8)
  24. 32:   }

我们此时假设有两个线程a和b在不停地进行判断和喂食操作。设置当前flag = true,此时线程a执行到004010F8处时,判断鱼还没有喂食,正准备执行指令004010F8,但是还没有来得及对falg进行设置,此时出现了线程调度。线程b运行到004010F8时,发现当前没有人喂食,所以执行喂食操作。等到b线程喂食结束,运行到00401113的时候,此时又出现了调度。线程a有继续运行,因为之前已经判断了当前还没有喂食,所以线程a继续进行了喂食了操作。所以,可怜的鱼,这一次就连续经历了两次喂食操作,估计有一部分鱼要撑死了。

当然鱼在这里之所以会出现撑死的情况,主要是因为line 24和line 25之间出现了系统调度。所以,我们在编写程序的时候必须有一个牢固的思想意识,如果缺少必须要的手段,程序可以任何时刻任何地点被调度,那此时公共数据的计算就会出现错误。

那么有没有方法避免这种情况的发生呢?当然有。朋友们可以继续关注下面的博客。

多线程的那点儿事(之数据同步)相关推荐

  1. Java多线程编程实战:模拟大量数据同步

    背景 最近对于 Java 多线程做了一段时间的学习,笔者一直认为,学习东西就是要应用到实际的业务需求中的.否则要么无法深入理解,要么硬生生地套用技术只是达到炫技的效果. 不过笔者仍旧认为自己对于多线程 ...

  2. 多线程的那点儿事(之大结局)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 多线程一直是我比较喜欢的话题,当然也是很多朋友比较害怕的话题.喜欢它,因为它确实可以提高pc的 ...

  3. Delphi中多线程用Synchronize实现VCL数据同步显示

    概述: VCL实现同步的另一种方法就是调用线程类的Synchronize的过程,此过程需要一个无参数的procedure,故在此procedure中无法传递参数值,但可以通过类的成员来实现.在类的Ex ...

  4. java 多线程跑数据_java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁...

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 packagethread_test;public class ThreadDemo1 extendsTh ...

  5. python进阶12并发之八多线程与数据同步

    原创博客地址:python进阶12并发之八多线程与数据同步 python并发首选进程,但偶尔有场景进程无法搞定,比如有些变量是无法序列化的,就无法使用工具包manager()的工具类进行共享.如果自己 ...

  6. 多线程操作数据库时为了防止数据的增删改的混乱该在数据库层还是程序层面上进行同步?

    多线程操作数据库时为了防止数据的增删改的混乱该在数据库层还是程序层面上进行同步? [问题点数:60分,结帖人jiao_zg] 不显示删除回复 显示所有回复 显示星级回复 显示得分回复 只显示楼主 收藏 ...

  7. 微服务之数据同步Porter

    Porter是一款数据同步中间件,主要用于解决同构/异构数据库之间的表级别数据同步问题. 背景 在微服务架构模式下深刻的影响了应用和数据库之间的关系,不像传统多个服务共享一个数据库,微服务架构下每个服 ...

  8. mq同步mysql数据 duplicate entry_MySQL数据同步之otter

    一.otter介绍 基于日志数据,用于MySQL或者ORACLE之间准实时同步数据. 用途: mysql/oracle互相同步 中间表/行记录同步 二.原理及架构图 otter整体模块 manager ...

  9. mysql 定时同步数据_MySQL数据同步之otter

    一.otter介绍 基于日志数据,用于MySQL或者ORACLE之间准实时同步数据. 用途: mysql/oracle互相同步 中间表/行记录同步 二.原理及架构图 otter整体模块 manager ...

最新文章

  1. 大型软件公司.Net面试题(一)
  2. python 线程等待_详解python多线程之间的同步(一)
  3. hudson pending - Waiting for next available executor
  4. 微服务2017年度报告出炉:4大客户画像,15%传统企业已领跑
  5. f(f(x)) = -x
  6. C#服务中Process的应用!
  7. c语言实现有限域模多项式_有限域计算简述
  8. 编写Play 2的模块,第2部分:拦截器
  9. numpy 中的 broadcasting(广播)机制
  10. Java从入门到精通 第10章 方法
  11. ValueError:Tensor(dense_1/Softmax:0, shape=(?, 3), dtype=float32) is not an element of this graph
  12. VB6 Socket编程
  13. qq邮箱登录收件服务器是什么,你好请问qq邮箱收件服务器不能为空是什么意思...
  14. 开始编写寄几的 CSS 基础库
  15. 用微型计算机原理做流水灯,微机原理流水灯设计.doc
  16. sencha touch总结
  17. 1u服务器系统风扇,1U工控服务器机箱介绍
  18. 1628:完成基于脚本的安装失败(手把手教学)
  19. 深入研究glibc内存管理器原理及优缺点
  20. mos管的rc吸收电路计算_一种反激式开关电源中MOS管的RC吸收电路的制作方法

热门文章

  1. 第19章,运维自动化之系统安装
  2. HDoj-1863-畅通project-并查集
  3. 聊聊RPC之Provider
  4. E-MapReduce解决hive comment中文乱码问题
  5. Chrome Beta for MacLinux正式发布下载
  6. 美将遣返庇护申请者至墨西哥 弱势人士有望豁免
  7. ElasticSearch权威指南学习(结构化查询)
  8. python基础之函数当中的装饰器
  9. Differential Geometry之第八章常Gauss曲率曲面
  10. iptables 开启3306端口