国嵌视频学习第六天——多线程

来源:互联网 发布:难吃的瓜子 知乎 编辑:程序博客网 时间:2024/06/06 02:35

线程

优点

使用多线程的理由之一是:
和进程相比,它是一种非常“节俭”的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种“昂贵”的多任务工作方式

运行于一个进程中的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需的时间也远远小于进程间切换所需要的时间

使用多线程的理由之二是:

线程间方便的通信机制。对不同进程来说,他们具有独立的数据空间,要进行数据的传递只能通过进程间通信的方式进行,这种方式不仅费时,而且不方便。线程则不然,只需定义一个全局变量。因为这个全局变量是属于进程的,而同一进程下的所有线程是共享数据空间的,所以一个线程的数据可以直接为其他线程所用

例如,之前所学的fork()函数,父子进程共享代码段,但是不共享数据段,而线程则是所有都是共享的

多线程程序作为一种多任务、并发的工作方式,有如下优点:

---使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。

---改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,分为几个独立或半独立的运行部分,这样的程序会利于理解和修改

多线程

LInux系统下的多线程遵循POSIX线程接口,称为pthread。编写linux西的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a

 

创建线程

#include <pthread.h>

int pthread_create(pthread_t * tidp, const pthread_attr_t * attr, void*(*start_rtn)(void),void * arg)

---tidp:线程id

---attr:线程属性(通常为空)

---start_rtn:线程要执行的函数。声明了一个函数指针start_rtn,返回值为void *,参数是void

创建线程之后,线程处于就绪态,因此进程继续执行下去(线程不执行)。

这里和fork是不同的。fork()函数调用后,子进程执行的是fork()函数之后的代码。而这里是去执行某个作者指定的函数

---argstart_rtn的参数

其实pthread其实质是一个整数。

---如果返回值是真,那么表示创建错误

编译

因为pthread的库不是linux系统的库,所以在进行编译的时候要加上 -lpthread

#gcc filename1 -lpthread -o filename2

thread_create.c   thread_int.c    thread_string.c   thread_struct.c   thread_share.c

终止线程

如果进程中任何一个线程中调用exit_exit,那么整个进程都会终止。线程的正常退出方式有:

(1).线程从启动例程中返回(比如return)

(2).线程可以被另一个进程终止

(3).线程自己调用pthread_exit函数

线程退出

#include <pthread.h>

void pthread_exit(void *rval_ptr)

功能:终止调用线程

rval_ptr:线程退出返回值的指针

thread_exit.c

线程等待

#inlude <pthread.h>

int pthread_join(pthread_t tid, void **rval_ptr);

功能:阻塞调用线程,直到指定的线程终止。

tid:等待退出的线程id

rval_ptr为一个用户定义的指针,它可以用来存储被等待线程的返回值

这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。如果执行成功,将返回0,如果失败则返回一个错误号

这与进程的等待不同,进程的等待是wait()

thread_join.c

线程标识

#include <pthread.h>

pthread_t pthread_self(void)

功能:获取调用线程的thread identifier

thread_id.c

清除

线程终止有两种情况:正常终止和非正常终止。线程主动调用pthread_exit或者从线程函数中return都将使线程正常退出,这是可预见的退出方式;非正常终止是线程在其他线程的干预下,或者由于自身运行出错(比如访问非法地址)而退出,这种退出方式是不可预见的。

不论是可预见的线程终止还是异常终止,都会存在资源释放的问题,如何保证线程终止时能顺利的释放掉自己所占用的资源,是一个必须考虑解决的问题。

pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中的终止动作(包括调用pthread_exit()和异常终止,不包括return)都将执行pthread_cleanup_push()所指定的清理函数。即在这段代码中有任何上述终止的语句,那么在执行该终止语句之前将调用pthread_cleanup_push()指定的函数(而该终止语句还将继续运行下去)。

#include <pthread.h>

void pthread_cleanup_push(void(*rtn)(void *), void *arg)

功能:将清除函数压入清除栈

---rtn:清除函数

---arg:清除函数的参数

void pthread_cleanup_pop(int execute)

功能:将清除函数弹出清除栈

---executeexecute执行到pthread_cleanup_pop()时是否在弹出清理函数的同时执行该函数,非0:执行;0:不执行

thread_clean.c

 

原创粉丝点击