吴裕雄--天生自然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 如下: 公共网关接 ...
随机推荐
- three.js的一些介绍
什么是 WebGL? WebGL(Web 图形库)是一种 JavaScript API,用于在任何兼容的 Web 浏览器中呈现交互式 3D 和 2D 图形,而无需使用插件.WebGL 通过引入一个与 ...
- SpringBoot之Feign调用方式比较
一:事发原因 两个东家都使用SpringCloud,巴拉巴拉用上了Spring全家桶,从eureka到ribbon,从ribbon到feign,从feign到hystrix,然后在使用feign的时候 ...
- 三、java基础-方法含义_重载_递归
1.java中方法: 方法的含义: 就是一个代码片段,可以完后某个特定的功能,可以重复利用: 定义方法的语法: [方法的修饰符列表] 方法的返回值类型 方法名{ java语句; } 注意 ...
- Day3-K-Can you solve this equation? HDU2199
Now,given the equation 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,can you find its solution between 0 and ...
- (转)spring mvc 中文乱码问题解决
在eclipse环境里,页面传输数据的时候通常用ISO-8859-1这个字符集可以用 str = new String(str.getBytes("ISO-8859-1"), &q ...
- Vue中 onmouseenter,onmouseleave,onmouseover,onmouseout的区别
今天在学Vue视频的时候,提到了这四个触发事件,我就想做下笔记: 1.onmouseenter和onmouseleave是一组:当鼠标进入指定区域的时候触发,但是不支持冒泡,进入或者离开子组件都不触发 ...
- 安装双版本python2 和 python 3 所产生得问题 解决yum对python依赖版本问题
错误 解决办法 一是升级yum 直接使用python3以上版本 二是修改yum的解释器为旧版本python2.7,即将连接文件 /usr/bin/python 软连接回 /usr/bi ...
- OpenResty 实现项目的灰度发布
1.安装 openresty 依赖模块: [root@Centos opt]# yum -y install pcre-devel openssl openssl-devel postgresql-d ...
- Thinkcmf任意漏洞包含漏洞分析复现
简介 ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理框架,底层采用ThinkPHP3.2.3构建.ThinkCMF提出灵活的应用机制,框架自身提供基础的管理功能,而开发者可以根据自身的 ...
- java面试题汇总,不断更新中。。。
JVM,并发,锁相关: 1.请你谈谈对volatile的理解,volatile是否存在伪共享问题. 2.cas你知道吗? 3.原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗? 4 ...