lienhua34
2014-11-08

进程控制三部曲中我们学习了进程的创建、终止以及获取终止状态等的进程控制原语。线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语。

表 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)——多线程编程(一):创建和终止线程的更多相关文章

  1. 孙鑫VC学习笔记:多线程编程

    孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified ...

  2. Python Web学习笔记之多线程编程

    本次给大家介绍Python的多线程编程,标题如下: Python多线程简介 Python多线程之threading模块 Python多线程之Lock线程锁 Python多线程之Python的GIL锁 ...

  3. python基础课程_学习笔记26:编程的乐趣

    编程的乐趣 编程柔术 当你坐下来,打算如何组织计划要定时,具体程序,然而,无论什么经验.在实现时间的函数的,你会逐渐学会了原来的设计,实用的新知识.我们不应该忽视沿途汲取的教训,相反,它们用于其他设计 ...

  4. 网络编程学习笔记:Socket编程

    文的主要内容如下: 1.网络中进程之间如何通信? 2.Socket是什么? 3.socket的基本操作 3.1.socket()函数 3.2.bind()函数 3.3.listen().connect ...

  5. python核心编程学习记录之多线程编程

  6. 多线程编程学习笔记——async和await(一)

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

  7. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

  8. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  9. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  10. 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端

    接上文 多线程编程学习笔记——使用异步IO 二.   编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...

随机推荐

  1. Oracle 安装报错 [INS-06101] IP address of localhost could not be determined 解决方法

    安装Oracle 11gR2,报错:[INS-06101] IP address of localhost could not be determined 出现这种错误是因为主机名和/etc/host ...

  2. [转]Oracle存储过程总结

    原文地址:https://www.cnblogs.com/tingbogiu/p/5641000.html 1.存储过程结构 1.1 第一个存储过程 create or replace procedu ...

  3. J.U.C--locks--AQS分析

    看一下AbstractQueuedSynchronizer(下面简称AQS)的子类就行知道,J.U.C中宣传的封装良好的同步工具类Semaphore.CountDownLatch.ReentrantL ...

  4. python 入门练习

    1.猜拳游戏 import randomimport sys #from random import randintdef guess(): ubuntu = random.randint(0,2)# ...

  5. 将已有jar添加至本地maven仓库

    官网链接:http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html 比如有 commons-dbutils-1.6.jar ...

  6. java.io.ByteArrayOutputStream 源码分析

    ByteArrayOutputStream 内部包含了一个缓冲区,缓冲区会随着数据的不断写入而自动增长,俗称内存流. 首先看一下俩个属性,buf是内部缓冲区,count是记录写入了多少个字节. pro ...

  7. C# 不借助第三个变量实现两整数交换

    c#中实现两个int变量的数值互换,在借助第三个变量做临时载体的情况下,非常简单. ; ; int c ; c = a; a = b; b = c; 如果不借助第三方变量,有几种实现的方法: 1.异或 ...

  8. CLR、内存分配和垃圾回收

    一.CLR CLR:即公共语言运行时(Common Language Runtime),是中间语言(IL)的运行时环境,负责将编译生成的MSIL编译成计算机可以识别的机器码,负责资源管理(内存分配和垃 ...

  9. json如何把键名作为变量?

    有时候在项目开发过程中,我们需要把json对象的键名作为一个变量.此时我们该怎么做呢? 传统的json数据格式如下: <script type="text/javascript&quo ...

  10. Controllerizing the ScrollViewer Thumbnail

    In the last post we created a ScrollViewer Thumbnail feature using a just a bit of Xaml and databind ...