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. THINKPHP短链接设置方法(路由设置)

    //路由设置(短链接设置) 'URL_ROUTER_ON' => true, 'URL_ROUTE_RULES' => array( 'log' => 'Login/index', ...

  2. EnumUtil

    EnumUtil.cs using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...

  3. [Linux实用工具]Linux监控工具munin的展示(Nginx)

    Munin的安装和配置可以参考第一篇文章: [Linux实用工具]Linux监控工具munin的安装和配置 http://www.cnblogs.com/rond/p/3757804.html Mun ...

  4. linux 重定向 标准错误与标准输出到同一文件

    Linux Shell 环境中的输入输出重定向,用符号<和>来表示.0.1和2分别表示标准输入.标准输出和标准错误. 1.重定向标准输出到文件: cat foo > foo.txt ...

  5. oozie java api提交作业

    今晚试验用java的api来提交代码,由于代码是在我机器上写的,然后提交到我的虚拟机集群当中去,所以中间产生了一个错误..要想在任意一台机器上向oozie提交作业的话,需要对hadoop的core-s ...

  6. 微信小程序——template的使用方法

    今天需要做一个[我的订单]页面,订单有几种状态,觉得把订单列表封装成一个模板更好.下面讲一下,如何用小程序自带的template构建一个模板. 1.构建订单列表模板页,命名为 [order.wxml] ...

  7. Change Data template dynamically

    1. Attached Property bound to task state. Any change will dynamically set data template.2. Visual St ...

  8. FatJar in 创新实训 自然语言交流系统

    Fat Jar Eclipse Plug-In是一个可以将Eclipse JavaProject的所有资源打包进一个可执行jar文件的小工具,可以方便的完成各种打包任务,我们经常会来打jar包,但是e ...

  9. Selenium常用操作汇总二——如何操作cookies(转)

    Web 测试中我们经常会接触到Cookies,一个Cookies主要属性有”所在域.name.value.有效日期和路径",下面来讲一下怎么操作Cookies. import java.ut ...

  10. Android 8 AudioPolicy 初始化

    记录一下AudioPolicy初始化过程. frameworks\av\media\audioserver\audioserver.rc service audioserver /system/bin ...