多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。
基于进程的多任务处理是程序的并发执行。
基于线程的多任务处理是同一程序的片段的并发执行。
多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径。
创建一个 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++ 多线程的更多相关文章

  1. 吴裕雄--天生自然C++语言学习笔记:C++ 标准库

    C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...

  2. 吴裕雄--天生自然C++语言学习笔记:C++ 动态内存

    栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的内存,在程序运行时可用于动态分配内存. 可以使用特殊的运算符为给定类型的变量在运行时分配堆内的内存,这会返回所分配的空间地址.这种运 ...

  3. 吴裕雄--天生自然C++语言学习笔记:C++ 类 & 对象

    C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计.类是 C++ 的核心特性,通常被称为用户定义的类型. 类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法.类中的 ...

  4. 吴裕雄--天生自然C++语言学习笔记:C++ 日期 & 时间

    C++ 标准库没有提供所谓的日期类型.C++ 继承了 C 语言用于日期和时间操作的结构和函数.为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 <ctime> 头文件. 有四 ...

  5. 吴裕雄--天生自然C++语言学习笔记:C++ 字符串

    C++ 提供了以下两种类型的字符串表示形式: C 风格字符串 C++ 引入的 string 类类型 C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持.字符串实际上是使用 null 字符 ...

  6. 吴裕雄--天生自然C++语言学习笔记:C++ 基本语法

    C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互. 对象 - 对象具有状态和行为.例如:一只狗的状态 - 颜色.名称.品种,行为 - 摇动.叫唤.吃.对象是类的实例. 类 - 类可 ...

  7. 吴裕雄--天生自然C++语言学习笔记:C++简介

    C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 年在贝尔实验室开始设计开发的.C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言.C++ 可运行于多种平台上,如 ...

  8. 吴裕雄--天生自然C++语言学习笔记:C++ 实例

    C++ 实例 - 输出 "Hello, World!" #include <iostream> using namespace std; int main() { co ...

  9. 吴裕雄--天生自然C++语言学习笔记:C++ STL 教程

    C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...

  10. 吴裕雄--天生自然C++语言学习笔记:C++ Web 编程

    什么是 CGI? 公共网关接口(CGI),是一套标准,定义了信息是如何在 Web 服务器和客户端脚本之间进行交换的. CGI 规范目前是由 NCSA 维护的,NCSA 定义 CGI 如下: 公共网关接 ...

随机推荐

  1. 吴裕雄--天生自然HADOOP操作实验学习笔记:单节点伪分布式安装

    实验目的 了解java的安装配置 学习配置对自己节点的免密码登陆 了解hdfs的配置和相关命令 了解yarn的配置 实验原理 1.Hadoop安装 Hadoop的安装对一个初学者来说是一个很头疼的事情 ...

  2. 爱屋吉屋官网、APP停运!互联网房屋中介真的迎来了至暗时刻吗?

    2018年底到2019年初,全球较差的经济大环境终于引来爆炸式的连锁反应.仅从国内的互联网行业来看,很多企业在浪潮退去后都只是在"裸泳".比如被爆料2018年全年亏损109亿元,且 ...

  3. SSH框架系列:Spring读取配置文件以及获取Spring注入的Bean

    分类: [java]2013-12-09 16:29 1020人阅读 评论(0) 收藏 举报 1.简介 在SSH框架下,假设我们将配置文件放在项目的src/datasource.properties路 ...

  4. Model Validation 和测试Post参数

    using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentM ...

  5. dotnet-千星项目OpenAuthNet基于NetCore21的快速开发框架

    下载

  6. 整合Spring时Service层为什么不做全局包扫描详解

    合Spring时Service层为什么不做全局包扫描详解 一.Spring和SpringMVC的父子容器关系 1.讲问题之前要先明白一个关系 一般来说,我们在整合Spring和SpringMVC这两个 ...

  7. Matplotlib 入门

    章节 Matplotlib 安装 Matplotlib 入门 Matplotlib 基本概念 Matplotlib 图形绘制 Matplotlib 多个图形 Matplotlib 其他类型图形 Mat ...

  8. eclipse console 查看全部的输出

    参考:https://blog.csdn.net/thatluck/article/details/52080736

  9. MySQL学习之SQL基础(一)DDL

    Sql基础 DDL (data defination language) 创建表 CREATE TABLE emp( ename varchar(10), hiredate date, sal dec ...

  10. 前端轻量级、简单、易用的富文本编辑器 wangEditor 的基本用法

    1.富文本编辑器市面上有很多,但是综合考虑之后wangEditor是最易用的框架,推荐使用 首先进入官网 http://www.wangeditor.com 基本是2中方式引入: 使用CDN://un ...