linux多线程学习(二)——线程的创建和退出

      在上一篇文章中对线程进行了简单的概述,它在系统中和编程的应用中,扮演的角色是不言而喻的。学习它、掌握它、吃透它是作为一个程序员的必须作为。在接下来的讲述中,所有线程的操作都是用户级的操作。在LINUX中,一般pthread线程库是一套通用的线程库,是由POSIX提出的,因此他的移植性是非常好的。

      创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_create。在线程创建之后,就开始运行相关的线程函数。在该函数运行结束,线程也会随着退出。这是其中退出线程的一种方法,另外一种退出线程的方法就是调用pthread_exit()函数接口,这是结束函数的主动行为。在这里要注意的是,在使用线程函数时,不要轻易调用exit()函数,因为这样会使整个进程退出,往往一个进程包含着多个线程,所以调用了exit()之后,所有该进程中的线程都会被结束掉。因此,在线程中,利用pthread_exit来替代进程中的exit。

      由于一个进程中的数据段是共享的,因此通常在线程退出之后,退出线程所占的资源并不会随着线程的结束而得到释放。正如进程之间可以调用wait()函数来同步中指并释放资源一样,线程之间也有类似的机制,那就是pthread_join函数.pthread_join可以将当前线程挂起,等待线程的结束,这个函数是一个阻塞函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待函数的资源就会被释放。

1、函数语法简述。

pthread_create

头文件:       pthread.h

函数原型:    int pthread_create (pthread_t* thread, pthread_attr_t* attr,

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

函数传入值: thread: 线程标识符

                   attr: 线程属性设置

                   start_routine:线程函数入口

                   arg:传递给线程函数的参数

返回值:       0: 成功

                   -1: 失败 

pthread_exit

头文件:      pthread.h

函数原型:   void pthread_exit (void*  retval);

函数传入值:retval:pthread_exit()调用者线程的返回值,可又其他函数如pthread_join来检索获取。

phread_join

头文件:      pthread.h

函数原型:   int pthread_join (pthread_t thread, void** thread_return);

函数传入值:thread:等待线程的标识符。

                  thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL值);

函数返回值:成功: 0

                  失败:-1

2、函数举例实现。

 

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>

void *thread_function(void *arg);
char message[] = "Hello world";

int main()
{
	int res;
	pthread_t a_thread;
	void *thread_result;

	res = pthread_create(&a_thread,NULL,thread_function,(void *)message);
	if(res != 0)
	{
		perror("Thread creation failed");
		exit(EXIT_FAILURE);

	}
	printf("Waiting for thread to finish...\n");
	res = pthread_join(a_thread,&thread_result);

	if(res != 0)
	{
		perror("Thread join failed");
		exit(EXIT_FAILURE);

	}

	printf("Thread joined,it returned %s\n",(char *)thread_result);
	printf("Message is now %s\n",message);
	exit(EXIT_SUCCESS);

}

void *thread_function(void *arg)
{
	printf("thread_function is running.Argument was %s\n",(char *)arg);
	sleep(3);
	strcpy(message,"Bye");
	pthread_exit("Thank you for the CPU time");
}

在上面的例子中只是简单的创建了线程、主动退出线程和挂起线程。在下一篇文章中,将讲述线程线的属性及其设定。

 

~~END~~

时间: 2024-04-10 07:06:46

linux多线程学习(二)——线程的创建和退出的相关文章

linux多线程学习(三)——线程属性设置。

在上一篇文章中,介绍了线程的创建和退出,以及相关函数的使用.其中pthread_create函数的第二个参数,是关于线程属性的设置,这也是今天所有讲述的.这些属性主要包括邦定属性.分离属性.堆栈地址.堆栈大小.优先级.其中系统默认的是非邦定.非分离.缺省1M的堆栈.与父进程同样级别的优先级.在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置. (1)绑定属性. 在LINUX中,采用的是"一对一"的线程机制.也就是一个用户线程对应一个内核线程.邦定属性

Linux多线程 创造新线程 线程的生命周期

创造新线程 一.线程的ID pthread_t:结构体(FreeBSD5.2.Mac OS10.3)/unsigned long int(linux)                /usr/include/bits/pthreadtypes.h 获取线程ID:pthread_self() 一个实例:获取主线程ID #include "apue.h" int main(){    pid_t pid;    pthread_t tid;     pid = getpid();    t

linux多线程学习(一)

进程是系统中程序执行和资源分配的基本单位.每个进程都有自己的数据段,代码段和堆栈段,这就导致了进程在进行切换等操作起到了现场保护作用.但是为了进一步减少处理机的空转时间支持多处理器和减少上下文切换开销,进程演化中出现了另外一个概念,这就是线程,也被人称为轻量级的进程.它是一个进程内的基本调度单位.线程是在共享的内存空间中并发的多道执行路径,它们共享一个进程的资源,比如文件描述符和信号处理等.因此, 大大减少了上下文切换的开销. 线程跟进程一样,都拥有一张控制表,线程将相关的变量值放在线程控制表中

Linux LVM学习总结&amp;mdash;&amp;mdash;创建卷组VG

    在Linux平台如何创建一个卷组(VG)呢?下面简单介绍一下卷组(VG)的创建步骤.本文实验平台为Red Hat Enterprise Linux Server release 6.6 (Santiago) 1: 查看当前卷组信息 查看服务器的卷组(VG).物理卷(PV).逻辑卷(LV)相关信息,在此之前,我们先来看看一些基本命令以及用法     vgcan命令介绍 :     查找系统中存在的LVM卷组,并显示找到的卷组列表.vgscan命令仅显示找到的卷组的名称和LVM元数据类型,要

【多线程】Java线程的创建

第2章 Java并行程序基础 2.2 初始线程:线程的基本操作 2.2.1 新建线程 新建线程方式一: Thread thread = new Thread(); thread.start(); new 一个对象thread后,执行这个对象的start()方法则会启动该线程的内部run()方法.run()方法这里没定义,下面会有讲. 但要注意!如果像下面用run()来启动新线程,它只会在当前线程中,串行执行run()中的代码. Thread thread2 = new Thread(); thr

linux多线程学习笔记六--一次性初始化和线程私有数据【转】

转自:http://blog.csdn.net/kkxgx/article/details/7513278 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,一次性初始化 以保证线程在调用资源时,确保资源已经被初始化,并且只初始化一次. 在传统的顺序编程中,一次性初始化经常通过使用布尔变量来管理.控制变量被静态初始化为0,而任何依赖于初始化的代码都能测试该变量.如果变量值仍然为0,则它能实行初始化,然后将变量置为1.以后检查的代码将跳过初始化. 但是在多线程程序设计中,事情就变的复杂的多

C#多线程学习(二)如何操纵一个线程

下面我们就动手来创建一个线程,使用Thread类创建线程时,只需提供线程入口即可.(线程入口使程序知道该让这个线程干什么事) 在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数. 打开你的VS.net,新建一个控制台应用程序(Console Application),编写完全控制一个线程的代码示例

linux多线程学习(六)——信号量实现同步。

信号量的互斥同步都是通过PV原语来操作的,我们可以通过注册两个信号量,让它们在互斥的问题上互动,从而达到同步.通过下面实例就可以很容易理解:   #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #include <errno.h> #define return_if_fail(p

linux多线程学习(七)——实现“生产者和消费者”

在上一篇文章中,利用信号量实现了线程间的互斥,这一篇将要利用信号量的互斥同步机制来实现一个经典实例,就是"生产者和消费者". 1.简单描述生产者和消费者的问题. 有一个缓冲区和两个线程:生产者和消费者.生产者把产品放入缓冲区,而消费者从缓冲区中拿走.当缓冲区满时,生产者必须等待:另外,当缓冲区空时,消费者必须等待,并且缓冲区不能同时进行生产者和消费者的操作. [cpp:nogutter] view plaincopy #include <stdio.h>     #incl