C++多线程编程分析-线程间通信
上文我们介绍了如何建立一个简单的多线程程序,多线程之间不可避免的需要进行通信。相比于进程间通信来说,线程间通信无疑是相对比较简单的。
首先我们来看看最简单的方法,那就是使用全局变量(静态变量也可以)来进行通信,由于属于同一个进程的各个线程是处于同一个进程空间中的,并且它们共享这个进程的各种资源,因此它们都可以毫无障碍的访问这个进程中的全局变量。当需要有多个线程来访问一个全局变量时,通常我们会在这个全局变量前加上volatile声明,来告诉编译器这个全局变量是易变的,让编译器不要对这个变量进行优化(至于编译器到底有没有按照你的要求来对volatile进行处理这个暂且不理)。
下面贴出一段简单的示例代码:
#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++多线程编程分析-线程间通信相关推荐
- python多线程编程(7):线程间通信
From: http://www.cnblogs.com/holbrook/archive/2012/03/21/2409031.html 很多时候,线程之间会有互相通信的需要.常见的情形是次要线程为 ...
- 多线程编程之三——线程间通讯
七.线程间通讯 一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信.这种线程间的通信不但是难以避免的,而 ...
- 【Java 并发编程】多线程、线程同步、死锁、线程间通信(生产者消费者模型)、可重入锁、线程池
并发编程(Concurrent Programming) 进程(Process).线程(Thread).线程的串行 多线程 多线程的原理 多线程的优缺点 Java并发编程 默认线程 开启新线程 `Ru ...
- Java多线程编程-(5)-使用Lock对象实现同步以及线程间通信
前几篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...
- Java多线程编程-(4)-线程间通信机制的介绍与使用
上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...
- java多线程编程(六)-线程间通信
一:线程通信介绍 线程通信是通过主动放弃对资源的使用,而让给其它线程的过程.合理的安排多个线程对同一资源的使用,即设计线程间的通信,可以完成很多复杂的任务. 二:线程通信实现 1,java.lang. ...
- Java多线程:线程间通信之Lock
Java 5 之后,Java在内置关键字sychronized的基础上又增加了一个新的处理锁的方式,Lock类. 由于在Java线程间通信:volatile与sychronized中,我们已经详细的了 ...
- Win32多线程编程(3) — 线程同步与通信
一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线程的 ...
- 线程间通信的几种方法_并发编程中的线程间通信
线程通信的目标是使线程间能够互相发送信号.另一方面,线程通信使线程能够等待其他线程的信号. 线程通信常用的方式有: wait/notify 等待 Volatile 内存共享 CountDownLatc ...
最新文章
- Catalan数推导(转载)
- 消费物联网与工业物联网有何区别?
- ARM中LDR伪指令与LDR加载指令
- C++ Byte转十六进制字符串输出
- 为什么还有那么多人用SVN?
- springmvc线程安全问题
- vue拦截器刷新登陆页面_vue页面跳转拦截器
- ghost64怎么装linux,CentOS 7.5上安装Node.js搭建Ghost个人博客
- 熟练运用计算机的重要性,计算机专业实习目的和意义
- win7修复计算机消失,详细教您win7 aero效果消失了怎么恢复
- 嵌入式linux项目,嵌入式linux项目开发(一)
- 关于PCIe有gen1升到gen3的方法
- refreshToken的作用讨论及几点疑惑
- 按键精灵手机版读取MYSQL_mysql,按键精灵,读取写入
- 面试题33:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 * 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
- stm32f4的数字摄像头接口(DCMI)使用
- linux希捷移动硬盘驱动,如果无法读取Seagate移动硬盘驱动器,该怎么办?
- 项目管理过程组与知识领域关系
- canvas.toDataURL()降低图片质量,以减少图片上传大小
- C++最后一次实验及实验总结
热门文章
- mysql保存特殊表情_让 MySQL 支持 emoji 表情等特殊字符存储
- python编程输入名字配对情侣网名_输入名字配对情侣网名 好听的情侣网名大全...
- 公众号滑动图代码_如何实现微信公众号文章“滑动查看更多”
- electron 屏幕标注_屏幕 | screen (screen) – Electron 中文开发手册
- 计算机组成与维修考试试题,期末考试试题计算机组成与维修.doc
- 怎么避免后台被搜索_复星保德信人寿保险有限公司星满意重大疾病保险怎么样?好不好?可信/靠谱吗?有什么优缺点/注意事项?值不值得买?一年多少钱?...
- python 物联网开发板_物联网学什么开发板好?
- 「第四篇」电赛控制题可以准备一些什么?
- 程序员新动向!大龄困惑详解!
- vivado不识别HLS生成的IP解决方法