线程的创建、终止、等待

线程的概念:

同一进程的多个线程共享同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

1. 文件描述符表

2. 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)

3. 当前工作目录

4. 用户id和组id

但有些资源是每个线程各有一份的:

1. 线程id

2. 上下文,包括各种寄存器的值、程序计数器和栈指针

3. 栈空间

4. errno变量

5. 信号屏蔽字

6. 调度优先级

注意:

编译时要加上-lpthread选项。

A. 创建线程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

void *(*start_routine) (void *), void *arg);

返回值:成功返回0,失败返回错误号。

以前学过的系统函数都是成功返回0,失败返回-1,而错误号保存在全局变量errno中,而pthread库的函数都是通过返回值返回错误号,由于pthread_create的错误码不保存在errno中,因此不能直接用perror(3)打印错误信息,可以先用strerror(3)把错误码转换成错误信息再打印。

pthread_create成功返回后,新创建的线程的id被填写到thread参数所指向的内存单元。我们知道进程id的类型是pid_t,每个进程的id在整个系统中是唯一的,调用getpid(2)可以获得当前进程的id,是一个正整数值。线程id的类型是thread_t,它只在当前进程中保证是唯一的。

B. 终止线程

注意:

1、任意一个线程函数中调用exit或_exit,整个进程的所有线程都终止。

2、从main函数中return,相当于调用exit,终止进程。

终止进程:

1、从线程函数return。

2、一个线程可以调用pthread_cancel终止同一进程中的另一个线程。

3、线程可以调用pthread_exit终止自己。

void pthread_exit(void *retval);

int pthread_cancel(pthread_t thread);

pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分 配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。

c. 线程等待

int pthread_join(pthread_t thread, void **retval);

返回值:成功返回0,失败返回错误号

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:

  1. 如果thread线程通过return返回,value_ptr所指向的单元里存放的是thread线程函数的返回值。

2. 如果thread线程被别的线程调用pthread_cancel异常终掉,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED。PTHREAD_CANCELED的值是-1

3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。如果对thread线程的终止状态不感兴趣,可以传NULL给value_ptr参数。

一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。但是线程也可以被置为detach 状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL。对一个尚未detach的线程调用pthread_join或pthread_detach都可以把该线程置为detach状态,也 就是说,不能对同一线程调用两次pthread_join,或者如果已经对一个线程调用 了pthread_detach就不能再调用pthread_join了。

int pthread_detach(pthread_t thread);

返回值:成功返回0,失败返回错误号。

  1 #include<stdio.h>
  2 #include<pthread.h>
  3 void* pthread_run1(void* arg)
  4 {
  5     printf("this is a thread1,pid:%d,tid:%ld\n",getpid(),pthread_self());
  6     return (void*)1;
  7 }
  8 
  9 void* pthread_run2(void* arg)
 10 {
 11     printf("this is a thread2,pid:%d,tid:%ld\n",getpid(),pthread_self());
 12     pthread_exit((void*)2);
 13 }
 14 
 15 void* pthread_run3(void* arg)
 16 {
 17     while(1)
 18     {
 19      printf("this is a thread3,pid:%d,tid:%ld\n",getpid(),pthread_self());
 20      sleep(1);
 21     }
 22      return NULL;
 23 }
 24 int main()
 25 {
 26     pthread_t tid;
 27     void* ret;
 28 
 29     pthread_create(&tid,NULL,pthread_run1,NULL);
 30     pthread_join(tid,&ret);
 31     printf("thread1,tid:%ld,return code:%d\n",tid,(int)ret);
 32 
 33     pthread_create(&tid,NULL,pthread_run2,NULL);
 34     pthread_join(tid,&ret);
 35     printf("thread2,tid:%ld,return code:%d\n",tid,(int)ret);
 36 
 37     pthread_create(&tid,NULL,pthread_run3,NULL);
 38     sleep(5);
 39     pthread_cancel(tid);
 40     pthread_join(tid,&ret);
 41     printf("thread3,tid:%ld,return code:%d\n",tid,(int)ret);
 42     return 0;
 43 }

结果:
[[email protected] THREAD]$ vim thread.c
[[email protected] THREAD]$ ./thread
this is a thread1,pid:2749,tid:-1216423056
thread1,tid:-1216423056,return code:1
this is a thread2,pid:2749,tid:-1216423056
thread2,tid:-1216423056,return code:2
this is a thread3,pid:2749,tid:-1216423056
this is a thread3,pid:2749,tid:-1216423056
this is a thread3,pid:2749,tid:-1216423056
this is a thread3,pid:2749,tid:-1216423056
this is a thread3,pid:2749,tid:-1216423056
thread3,tid:-1216423056,return code:-1
时间: 2024-08-06 09:21:41

线程的创建、终止、等待的相关文章

线程的创建,等待与终止

一.线程的创建 基础知识 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成. 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源. 一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行.由于线程之间的相互制约,致使线程在运行中呈现出间断性

java 加入一个线程、创建有响应的用户界面 。 示例代码

javajava 加入一个线程.创建有响应的用户界面 . 示例代码 来自thinking in java 4 21章  部分代码  目录21.2.11 thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155 package org.rui.thread.concurrent; /** * 加入一个线程 * 一个线程可以在其他线程之上调用join()方法,其效果是等待一段时间直到第二个线程结束才继续执行

嵌入式?探讨父子线程、进程终止顺序不同产生的结果_skdkjxy_新浪博客

#bsPanelHolder,#sinaads_pdps54771{display:none;}a.bsSiteLink{text-decoration:none;color:#666;}a.bsSiteLink:hover{text-decoration:underline;}a.bshareDiv{overflow:hidden;height:16px;line-height:18px;font-size:14px;color:#333;padding-left:0;}a.bshareDiv

Linux C线程的创建和使用 [转]

1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中 去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多 线程就意味着多进程.现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux. 为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题. 使用多线程的理由之一是和进程相比

Windows核心编程之创建可等待定时器及其APC回调

概述 创建可等待定时器是Windows内部线程同步的方式之一,本文简单讲述如何使用这一内核对象进行线程同步. 使用方法 创建对象: //创建事件内核对象,默认未触发状态 HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL); 设置对象属性: CreateWaitableTimer创建完成后内核对象处于未触发状态,需要使用API BOOL WINAPI SetWaitableTimer( __in HANDLE hTimer, __in con

管理线程之创建线程

主要的线程管理包含:1.创建线程.2.等待它结束或在后台执行. 3.向线程函数传递參数.更改线程对象全部权.4.选择线程和使用特定线程. 创建线程 线程在创建线程对象时開始执行,创建线程对象使用std::thread.像上节最后那个函数一样.最简单的情况是线程对象创建后执行一个无返回值.无參数的函数. 这个函数在线程中执行直到返回,这时线程终止. 想一下最复杂的情况,线程执行的函数可能是个函数对象.须要传递參数,执行一系列独立的操作.这些操作须要系统的一些信息,直到接收到某个信号终止. 线程执行

漫谈并发编程(二):java线程的创建与基本控制

java线程的创建 定义任务 在java中使用任务这个名词来表示一个线程控制流的代码段,用Runnable接口来标记一个任务,该接口的run方法为线程执行的代码段. public class LiftOff implements Runnable { protected int countDown = 10; private static int taskCount = 0; private final int id = taskCount++; public void run() { whil

线程的创建和控制

线程的定义:线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源.一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行.由于线程之间的相互制约,致使线程在运行中呈现出间断性.线程也有就

linux内核线程的创建与销毁

linux将创建内核线程的工作交给了一个专门的内核线程kthreadd来完成,该线程会检查全局链表kthread_create_list,如果为NULL,就会调schedule()放弃cpu进入睡眠状态,否则就取下该链表中的一项创建对应的线程.本文就从khtreadd内核线程的创建开始来展示一下内核线程的创建过程.1 kthreaddlinux2.6.30,创建内核线程是通过kethradd内核守护线程来完成的,虽然机制上有所变化,但是最终还是调用do_fork来完成线程的创建.Kthreadd