上文我们介绍了如何建立一个简单的多线程程序,多线程之间不可避免的需要进行通信。相比于进程间通信来说,线程间通信无疑是相对比较简单的。

首先我们来看看最简单的方法,那就是使用全局变量(静态变量也可以)来进行通信,由于属于同一个进程的各个线程是处于同一个进程空间中的,并且它们共享这个进程的各种资源,因此它们都可以毫无障碍的访问这个进程中的全局变量。当需要有多个线程来访问一个全局变量时,通常我们会在这个全局变量前加上volatile声明,来告诉编译器这个全局变量是易变的,让编译器不要对这个变量进行优化(至于编译器到底有没有按照你的要求来对volatile进行处理这个暂且不理)。

下面贴出一段简单的示例代码:

#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
volatile int ThreadData = 0;
void ThreadProcess()
{
    for(int i=0; i<6; i++)
    {
        ThreadData += 1000;
        Sleep(1000);
        printf("Sub  Thread Tick %5d! %5d\n",(i+1)*1000, ThreadData);
    }
    printf("Exit Sub Thread!\n");
    }
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hThread;
    DWORD ThreadID;
    hThread=CreateThread(NULL,
                     0,
                     (LPTHREAD_START_ROUTINE)ThreadProcess,
                     NULL,
                     0,
                     &ThreadID);
    
    for(int i=0; i<10; i++)
    {
        ThreadData -= 600;
        Sleep(600);
        printf("Main Thread Tick %5d! %5d\n", (i+1)*600, ThreadData);
    }
    printf("Main Thread Loop Finished! \n");
    system("pause");
    return 0;
}

除了全局变量之外,还有其他的方法,比如利用消息机制等来实现线程间通信。这个就不详细解释了,关于消息机制,详情请看Windows消息机制概述 。

下面,关于多线程中的全局变量,我来介绍点有点偏题的东西:
线程局部存储(TLS)
    进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。
  如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变量),就需要新的机制来实现。这就是TLS。
  线程局部存储在不同的平台有不同的实现,可移植性不太好。 
  方法一:每个线程创建时系统给它分配一个LPVOID指针的数组(叫做TLS数组),这个数组从C编程角度是隐藏着的不能直接访问,需要通过一些C API函数调用访问。首先定义一些DWORD线程全局变量或函数静态变量,准备作为各个线程访问自己的TLS数组的索引变量。一个线程使用TLS时,第一步在线程内调用TlsAlloc()函数,为一个TLS数组索引变量与这个线程的TLS数组的某个槽(slot)关联起来,例如获得一个索引变量:
  global_dwTLSindex=TLSAlloc();
  注意,此步之后,当前线程实际上访问的是这个TLS数组索引变量的线程内的拷贝版本。也就说,不同线程虽然看起来用的是同名的TLS数组索引变量,但实际上各个线程得到的可能是不同DWORD值。其意义在于,每个使用TLS的线程获得了一个DWORD类型的线程局部静态变量作为TLS数组的索引变量。C/C++原本没有直接定义线程局部静态变量的机制,所以在如此大费周折。
  第二步,为当前线程动态分配一块内存区域(使用LocalAlloc()函数调用),然后把指向这块内存区域的指针放入TLS数组相应的槽中(使用TlsValue()函数调用)。
  第三步,在当前线程的任何函数内,都可以通过TLS数组的索引变量,使用TlsGetValue()函数得到上一步的那块内存区域的指针,然后就可以进行内存区域的读写操作了。这就实现了在一个线程内部这个范围处处可访问的变量。
  最后,如果不再需要上述线程局部静态变量,要动态释放掉这块内存区域(使用LocalFree()函数),然后从TLS数组中放弃对应的槽(使用TlsFree()函数)。
  方法二:
  直接声明这个变量是各个线程有自己拷贝的线程局部静态变量:
  __declspec( thread ) int var_name;

C++多线程编程分析-线程间通信相关推荐

  1. python多线程编程(7):线程间通信

    From: http://www.cnblogs.com/holbrook/archive/2012/03/21/2409031.html 很多时候,线程之间会有互相通信的需要.常见的情形是次要线程为 ...

  2. 多线程编程之三——线程间通讯

    七.线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而 ...

  3. 【Java 并发编程】多线程、线程同步、死锁、线程间通信(生产者消费者模型)、可重入锁、线程池

    并发编程(Concurrent Programming) 进程(Process).线程(Thread).线程的串行 多线程 多线程的原理 多线程的优缺点 Java并发编程 默认线程 开启新线程 `Ru ...

  4. Java多线程编程-(5)-使用Lock对象实现同步以及线程间通信

    前几篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...

  5. Java多线程编程-(4)-线程间通信机制的介绍与使用

    上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...

  6. java多线程编程(六)-线程间通信

    一:线程通信介绍 线程通信是通过主动放弃对资源的使用,而让给其它线程的过程.合理的安排多个线程对同一资源的使用,即设计线程间的通信,可以完成很多复杂的任务. 二:线程通信实现 1,java.lang. ...

  7. Java多线程:线程间通信之Lock

    Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...

  8. Win32多线程编程(3) — 线程同步与通信

    一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线程的 ...

  9. 线程间通信的几种方法_并发编程中的线程间通信

    线程通信的目标是使线程间能够互相发送信号.另一方面,线程通信使线程能够等待其他线程的信号. 线程通信常用的方式有: wait/notify 等待 Volatile 内存共享 CountDownLatc ...

最新文章

  1. Catalan数推导(转载)
  2. 消费物联网与工业物联网有何区别?
  3. ARM中LDR伪指令与LDR加载指令
  4. C++ Byte转十六进制字符串输出
  5. 为什么还有那么多人用SVN?
  6. springmvc线程安全问题
  7. vue拦截器刷新登陆页面_vue页面跳转拦截器
  8. ghost64怎么装linux,CentOS 7.5上安装Node.js搭建Ghost个人博客
  9. 熟练运用计算机的重要性,计算机专业实习目的和意义
  10. win7修复计算机消失,详细教您win7 aero效果消失了怎么恢复
  11. 嵌入式linux项目,嵌入式linux项目开发(一)
  12. 关于PCIe有gen1升到gen3的方法
  13. refreshToken的作用讨论及几点疑惑
  14. 按键精灵手机版读取MYSQL_mysql,按键精灵,读取写入
  15. 面试题33:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 * 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
  16. stm32f4的数字摄像头接口(DCMI)使用
  17. linux希捷移动硬盘驱动,如果无法读取Seagate移动硬盘驱动器,该怎么办?
  18. 项目管理过程组与知识领域关系
  19. canvas.toDataURL()降低图片质量,以减少图片上传大小
  20. C++最后一次实验及实验总结

热门文章

  1. mysql保存特殊表情_让 MySQL 支持 emoji 表情等特殊字符存储
  2. python编程输入名字配对情侣网名_输入名字配对情侣网名 好听的情侣网名大全...
  3. 公众号滑动图代码_如何实现微信公众号文章“滑动查看更多”
  4. electron 屏幕标注_屏幕 | screen (screen) – Electron 中文开发手册
  5. 计算机组成与维修考试试题,期末考试试题计算机组成与维修.doc
  6. 怎么避免后台被搜索_复星保德信人寿保险有限公司星满意重大疾病保险怎么样?好不好?可信/靠谱吗?有什么优缺点/注意事项?值不值得买?一年多少钱?...
  7. python 物联网开发板_物联网学什么开发板好?
  8. 「第四篇」电赛控制题可以准备一些什么?
  9. 程序员新动向!大龄困惑详解!
  10. vivado不识别HLS生成的IP解决方法