吴裕雄--天生自然C++语言学习笔记:C++ 多线程
多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。
基于进程的多任务处理是程序的并发执行。
基于线程的多任务处理是同一程序的片段的并发执行。
多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径。
创建一个 POSIX 线程:
#include <pthread.h>
pthread_create (thread, attr, start_routine, arg)
在这里,pthread_create 创建一个新的线程,并让它可执行。下面是关于参数的说明:
thread 指向线程标识符指针。
attr 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。
start_routine 线程运行函数起始地址,一旦线程被创建就会执行。
arg 运行函数的参数。它必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。
创建线程成功时,函数返回 ,若返回值不为 则说明创建线程失败。
终止一个 POSIX 线程:
#include <pthread.h>
pthread_exit (status)
在这里,pthread_exit 用于显式地退出一个线程。通常情况下,pthread_exit() 函数是在线程完成工作后无需继续存在时被调用。
如果 main() 是在它所创建的线程之前结束,并通过 pthread_exit() 退出,那么其他线程将继续执行。否则,它们将在 main() 结束时自动被终止。
以下简单的实例代码使用 pthread_create() 函数创建了 个线程,每个线程输出"Hello Runoob!":
#include <iostream>
// 必须的头文件
#include <pthread.h> using namespace std; #define NUM_THREADS 5 // 线程的运行函数
void* say_hello(void* args)
{
cout << "Hello Runoob!" << endl;
return ;
} int main()
{
// 定义线程的 id 变量,多个变量使用数组
pthread_t tids[NUM_THREADS];
for(int i = ; i < NUM_THREADS; ++i)
{
//参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
if (ret != )
{
cout << "pthread_create error: error_code=" << ret << endl;
}
}
//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
pthread_exit(NULL);
}
使用 -lpthread 库编译下面的程序: $ g++ test.cpp -lpthread -o test.o
以下简单的实例代码使用 pthread_create() 函数创建了 个线程,并接收传入的参数。每个线程打印一个 "Hello Runoob!" 消息,并输出接收的参数,然后调用 pthread_exit() 终止线程。
#include <iostream>
#include <cstdlib>
#include <pthread.h> using namespace std; #define NUM_THREADS 5 void *PrintHello(void *threadid)
{
// 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
int tid = *((int*)threadid);
cout << "Hello Runoob! 线程 ID, " << tid << endl;
pthread_exit(NULL);
} int main ()
{
pthread_t threads[NUM_THREADS];
int indexes[NUM_THREADS];// 用数组来保存i的值
int rc;
int i;
for( i=; i < NUM_THREADS; i++ ){
cout << "main() : 创建线程, " << i << endl;
indexes[i] = i; //先保存i的值
// 传入的时候必须强制转换为void* 类型,即无类型指针
rc = pthread_create(&threads[i], NULL,
PrintHello, (void *)&(indexes[i]));
if (rc){
cout << "Error:无法创建线程," << rc << endl;
exit(-);
}
}
pthread_exit(NULL);
}
可以在线程回调中传递任意的数据类型,因为它指向 void,如下面的实例所示:
#include <iostream>
#include <cstdlib>
#include <pthread.h> using namespace std; #define NUM_THREADS 5 struct thread_data{
int thread_id;
char *message;
}; void *PrintHello(void *threadarg)
{
struct thread_data *my_data; my_data = (struct thread_data *) threadarg; cout << "Thread ID : " << my_data->thread_id ;
cout << " Message : " << my_data->message << endl; pthread_exit(NULL);
} int main ()
{
pthread_t threads[NUM_THREADS];
struct thread_data td[NUM_THREADS];
int rc;
int i; for( i=; i < NUM_THREADS; i++ ){
cout <<"main() : creating thread, " << i << endl;
td[i].thread_id = i;
td[i].message = (char*)"This is message";
rc = pthread_create(&threads[i], NULL,
PrintHello, (void *)&td[i]);
if (rc){
cout << "Error:unable to create thread," << rc << endl;
exit(-);
}
}
pthread_exit(NULL);
}
可以使用以下两个函数来连接或分离线程:
pthread_join (threadid, status)
pthread_detach (threadid)
pthread_join() 子程序阻碍调用程序,直到指定的 threadid 线程终止为止。当创建一个线程时,它的某个属性会定义它是否是可连接的(joinable)或可分离的(detached)。只有创建时定义为可连接的线程才可以被连接。如果线程创建时被定义为可分离的,则它永远也不能被连接。
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h> using namespace std; #define NUM_THREADS 5 void *wait(void *t)
{
int i;
long tid; tid = (long)t; sleep();
cout << "Sleeping in thread " << endl;
cout << "Thread with id : " << tid << " ...exiting " << endl;
pthread_exit(NULL);
} int main ()
{
int rc;
int i;
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
void *status; // 初始化并设置线程为可连接的(joinable)
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for( i=; i < NUM_THREADS; i++ ){
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], NULL, wait, (void *)&i );
if (rc){
cout << "Error:unable to create thread," << rc << endl;
exit(-);
}
} // 删除属性,并等待其他线程
pthread_attr_destroy(&attr);
for( i=; i < NUM_THREADS; i++ ){
rc = pthread_join(threads[i], &status);
if (rc){
cout << "Error:unable to join," << rc << endl;
exit(-);
}
cout << "Main: completed thread id :" << i ;
cout << " exiting with status :" << status << endl;
} cout << "Main: program exiting." << endl;
pthread_exit(NULL);
}
吴裕雄--天生自然C++语言学习笔记:C++ 多线程的更多相关文章
- 吴裕雄--天生自然C++语言学习笔记:C++ 标准库
C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 动态内存
栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存. 可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址.这种运 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 类 & 对象
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计.类是 C++ 的核心特性,通常被称为用户定义的类型. 类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法.类中的 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 日期 & 时间
C++ 标准库没有提供所谓的日期类型.C++ 继承了 C 语言用于日期和时间操作的结构和函数.为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 <ctime> 头文件. 有四 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 字符串
C++ 提供了以下两种类型的字符串表示形式: C 风格字符串 C++ 引入的 string 类类型 C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持.字符串实际上是使用 null 字符 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 基本语法
C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互. 对象 - 对象具有状态和行为.例如:一只狗的状态 - 颜色.名称.品种,行为 - 摇动.叫唤.吃.对象是类的实例. 类 - 类可 ...
- 吴裕雄--天生自然C++语言学习笔记:C++简介
C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 年在贝尔实验室开始设计开发的.C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言.C++ 可运行于多种平台上,如 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 实例
C++ 实例 - 输出 "Hello, World!" #include <iostream> using namespace std; int main() { co ...
- 吴裕雄--天生自然C++语言学习笔记:C++ STL 教程
C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ Web 编程
什么是 CGI? 公共网关接口(CGI),是一套标准,定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的. CGI 规范目前是由 NCSA 维护的,NCSA 定义 CGI 如下: 公共网关接 ...
随机推荐
- python中metaclass的工作原理
class TMetaclass(type): def __new__(cls, name, bases, attrs): print(cls, name, bases, attrs) return ...
- Visual Studio Code 格式化ESlint 的方法
既然要格式化ESlint,就不得不先介绍一下什么是ESlint.后面再介绍格式化的方法 1.ESlint ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具 ...
- Py2与Py3的区别
总结Py2 与Py3 的区别 1 编码区别 在Python2中有两种字符串类型str和Unicode. 默认ASCII python2 str类型,相当于python3中的bytes类型 python ...
- MySQL 常用SQL 汇总
1.查看当前应用连接,连接数突增排查 select user,SUBSTRING_INDEX(host,':',1) as ip , count(*) as count,db from informa ...
- AngularJs 禁止模板缓存
因为AngularJs的特性(or 浏览器本身的缓存?),angular默认的HTML模板加载都会被缓存起来.导致每次修改完模板之后都得经常需要清除浏览器的缓存来保证浏览器去获得最新的html模板,自 ...
- HDU 3065 病毒侵袭持续中 (模板题)
病毒侵袭持续中 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- ffmpeg 学习: 003-关键函数介绍
背景 了解一些关键函数对于开发的帮助比较大. avformat_open_input FFMPEG 打开媒体的过程开始于 avformat_open_input,因此该函数的重要性不可忽视. 在该函数 ...
- is application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem
最近试着了解 c++,接触到了QT,写了一个测试程序,在开发环境下正常后移到非开发环境,报错 网上找资料说是少了platforms文件夹中的dll,把里面所有的dll复制到执行程序目录,还是提示,继续 ...
- shiro缓存配置
realm的缓存 方法一: 在securityManager配置中添加cacheManager配置项,会注入到realm中. 方法二:在realm中配置. realm本身实现了CacheManager ...
- Windows 10工程版本泄露全新设计的操作中心圆角样式
早些时候微软错误地向Windows 10所有测试通道推送内部工程版本,该版本构建后尚未经过微软内部测试. 当然本身微软也没准备推送所以该版本里很多新功能未被关闭,而成功升级的用户则可以立即查看这些功能 ...