UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程
lienhua34
2014-11-08
在进程控制三部曲中我们学习了进程的创建、终止以及获取终止状态等的进程控制原语。线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语。
| 进程原语 | 线程原语 | 描述 |
| fork | pthread_create | 创建新的控制流 |
| exit | pthread_exit | 从现有的控制流中退出 |
| waitpid | pthread_join | 从控制流中得到退出状态 |
| atexit | pthread_cleanup_push | 注册在退出控制流时调用的函数 |
| getpid | pthread_self | 获取控制流的 ID |
| abort | pthread_cancel | 请求控制流的非正常退出 |
1 线程
每个线程都有一个线程 ID,线程只在它所属的进程环境中有效。线程ID 使用pthread_t 表示。可以通过调用pthread_self 函数获取线程自身的线程 ID,
#include <pthread.h>
pthread_t pthread_self(void);
返回值:调用线程的线程ID
线程 ID 不一定是一个非负整数,也有可能是一个结构体。所以,要对比两个线程是否相同,必须使用pthread_equal 函数来进行,
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
返回值:若相等则返回非0值,否则返回0
2 线程的创建
可以通过调用pthread_create 来创建新的线程,
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
返回值:若成功则返回0,否则返回错误编码
其中,参数 tidp 用于返回成功创建的新线程的线程 ID。参数 attr 用于定制各种不同的线程属性,如果设置为 NULL,表示创建一个默认属性的线程。成功创建的新线程将从参数start_rtn 所指向的函数开始执行,该函数接收一个 void * 的参数 arg,并返回一个 void * 的返回值。
注意:pthread_create 失败的时候返回的是错误编码,表示我们可以通过调用 strerror 函数来获取具体的错误信息。
下面我们来看一个创建新进程的例子,
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h> void *
my_thread(void *arg)
{
printf("in new thread. tid: %u\n", (unsigned int)pthread_self());
return ((void *));
} int
main(void)
{
int err;
pthread_t tid; err = pthread_create(&tid, NULL, my_thread, NULL);
if ( err != ) {
printf("can't create thread: %s\n", strerror(err));
exit(-);
}
printf("in main thread: %u\n", (unsigned int)pthread_self());
sleep();
exit();
}
编译该程序,生成并执行文件pthread_create_demo。从下面的运行结果,我们可以看到在 main 函数和my_thread 函数打印的线程 ID 是不一样的。
lienhua34:demo$ gcc -o pthread_create_demo -pthread pthread_create_demo.c
lienhua34:demo$ ./pthread_create_demo
in main thread:
in new thread. tid:
3 线程终止
如果进程中的任一线程调用了exit、_Exit 或_exit 函数,那么整个进程都将会终止。那如果我们只是想单独的终止一个线程呢?有三种方式,
1. 线程从启动例程中返回,返回值即为线程的退出码。
2. 被同一个进程中的其他线程取消。
3. 线程调用函数pthread_exit。
pthread_exit 函数的声明如下,
#include <pthread.h>
void pthread_exit(void *rval_ptr);
进程中其它线程可以通过调用pthread_join 来获取指定线程的退出码。
#include <pthread.h>
int pthread_join(pthread_t tid, void **rval_ptr);
返回值:若成功则返回0,否则返回错误编号
pthread_join 函数会使调用线程一直阻塞,直到指定的线程终止。如果指定线程只是从它的启动例程中返回,rval_ptr 将包含返回码。如果线程被取消,由rval_ptr 指定的内存单元将被置为PTHREAD_CANCELED。
下面我们来看一个线程终止的例子,
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h> void *
thr_fn1(void *arg)
{
printf("in thread 1\n");
return ((void *));
} void *
thr_fn2(void *arg)
{
printf("in thread 2\n");
pthread_exit((void *));
} int
main(void)
{
int err;
pthread_t tid1, tid2;
void *tret; err = pthread_create(&tid1, NULL, thr_fn1, NULL);
if ( err != ) {
printf("can't create thread 1: %s\n", strerror(err));
exit(-);
} err = pthread_create(&tid2, NULL, thr_fn2, NULL);
if (err != ) {
printf("can't create thread 2: %s\n", strerror(err));
exit(-);
} err = pthread_join(tid1, &tret);
if (err != ) {
printf("can't join with thread 1: %s\n", strerror(err));
exit(-);
}
printf("thread 1 exit code: %d\n", (int)tret); err = pthread_join(tid2, &tret);
if (err != ) {
printf("can't join with thread 2: %s\n", strerror(err));
exit(-);
}
printf("thread 2 exit code: %d\n", (int)tret); exit();
}
pthread_exit_demo.c
编译该程序,生成并执行文件pthread_exit_demo,
lienhua34:demo$ gcc -o pthread_exit_demo -pthread pthread_exit_demo.c
lienhua34:demo$ ./pthread_exit_demo
in thread
in thread
thread exit code:
thread exit code:
(done)
UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程的更多相关文章
- 孙鑫VC学习笔记:多线程编程
孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010 HQU Email:zgzhaobo@gmail.com QQ:452728574 Latest Modified ...
- Python Web学习笔记之多线程编程
本次给大家介绍Python的多线程编程,标题如下: Python多线程简介 Python多线程之threading模块 Python多线程之Lock线程锁 Python多线程之Python的GIL锁 ...
- python基础课程_学习笔记26:编程的乐趣
编程的乐趣 编程柔术 当你坐下来,打算如何组织计划要定时,具体程序,然而,无论什么经验.在实现时间的函数的,你会逐渐学会了原来的设计,实用的新知识.我们不应该忽视沿途汲取的教训,相反,它们用于其他设计 ...
- 网络编程学习笔记:Socket编程
文的主要内容如下: 1.网络中进程之间如何通信? 2.Socket是什么? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 3.3.listen().connect ...
- python核心编程学习记录之多线程编程
- 多线程编程学习笔记——async和await(一)
接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...
- 多线程编程学习笔记——async和await(二)
接上文 多线程编程学习笔记——async和await(一) 三. 对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...
- 多线程编程学习笔记——async和await(三)
接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五. 处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...
- 多线程编程学习笔记——使用异步IO(一)
接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...
- 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端
接上文 多线程编程学习笔记——使用异步IO 二. 编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...
随机推荐
- 2. CNN卷积网络-前向传播算法
1. CNN卷积网络-初识 2. CNN卷积网络-前向传播算法 3. CNN卷积网络-反向更新 1. 前言 我们已经了解了CNN的结构,CNN主要结构有输入层,一些卷积层和池化层,后面是DNN全连接层 ...
- tensorflow入门 (一)
转载:作者:地球的外星人君链接:https://www.zhihu.com/question/49909565/answer/207609620来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...
- 小米手机刷机工具MiFlash怎么用
刷机包的获取:直接登陆MIUI系统官网(miui.com),在其“下载”栏目中根据手机类型找到对应的刷机包进行下载. 接下来就需要下载“小米手机刷机工具MiFlash”程序,可以直接从以下地址中获 ...
- Lamda表达式的参数捕获,太酷了
lamda表达式有了参数捕获这个功能,让Action这个委托变得无所不能.Action委托就是无参数,无返回值的一个代理类型. 它只能对应于下面这种类型的函数声明. public void Funct ...
- 微信怎样做SEO
微信也能做SEO.大家还不知道吧?今天上海SEO优化公司就和大家解说在微信上要怎么做SEO优化. 微信也有SEO?你会不会觉得我是说笑呢.事实上还就是.我也找不到什么好名词来介绍公众号上的排名,就用微 ...
- 关于网页游戏断线重连的思路和demo求助
http://bbs.9ria.com/thread-146997-1-1.html —————————————————————————————————————————————————— 1:俺有什么 ...
- C#里的SubString和Convert.ToDateTime
1.C#里的SubString String.SubString(int index,int length) index:开始位置,从0开始 length:你要取的子字符串的长度 2.C#语言 ...
- native-base中icon不能正确显示[转]
初次接触native-base,在使用它的Icon组件的时候碰到了一个问题:图标没能正确显示!(在expo调试模式下是正常的) native-base官网给的使用Icon的例子 怎么找到适合我的图标呢 ...
- 优雅的运用 Kotlin 的 null safety 特性,而不要简单的直接用 !!双感叹号
对于 Null 的检查是 Kotlin 的特点之一.强制你在编码过程中考虑变量是否可为 null,因此可以避免很多在 Java 中隐藏的 NullPointerException. 但是,当你用插件直 ...
- Sword websocket分析一
什么是WebSocket WebSocket是一个允许Web应用程序(通常指浏览器)与服务器进行双向通信的协议. HTML5的WebSocket API主要是为浏览器端提供了一个基于TCP协议实现全双 ...