Linux_线程基本函数

Linux_线程基本函数

线程库没有包含在系统库中,编译时要进行链接gcc -l pthread

线程包括主线程和次线程,线程时平等的,共享数据短,栈空间,唯一不同的是栈空间不同。

tid不要打印      

2.pthread_cread(tid,&attr,func,&arg)  //成功返回0,错误返回错误码

  tid:线程id号;attr:线程属性(大多填写NULL,后面会祥解)

  func:启动例程;args:启动例程的参数

  如:pthread_create(tid,NULL,doWork,NULL);

3.pthread_join(tid,void **retval)

  功能:等待线程号为tid的线程执行结束后回收线程资源,类似于进程的wait()函数,会阻塞。任何一个线程都可以回收其它线程

  tid:等待回收的线程

  retval:1.可以作为线程结束返回码。判断线程是否正常结束

2.接收线程结束时的返回的数据空间

 

4.pthread_exit(void *retval)

  功能:结束线程,并返回结束码:可以用0,1表示线程是否正常返回

也可以返回一个数据的地址,方便其他线程调用

 

5.Pthread_cancel(tid) [A1]  //成功返回0,失败返回erro

  功能:对线程号为tid的线程发送取消请求

  注:发送成功并不代表线程tid就会结束

  原因:每个线程都有取消选项,是相应取消请求要看取消选项。

  取消选项包括:可取消状态和可取消类型

【1】可取消状态包含两种:

① PTHREAD_CANCEL_ENABLE:可以被取消,但是具体行为还要看取消类型

② PTHREAD_CANCEL_DISABLE:不可以被取消

  pthread_setcancelstate()://设置线程取消状态

【2】可取消类型也包括两种:

① PTHREAD_CANCEL_DEFERRED  延迟取消(调用pthread_cancel并不会立即终止线程,而是继续运行,达到某个取消点时才终止)

② PTHREAD_CANCEL_ASYNCHRONOUS 导步取消(线程可以在任何时间取消)

  pthread_setcanceltype() //设置线程取消类型(理解:类似于进程上锁的机制,在这期间是不能被取消的,保证数据完整)

  pthread_testcancel()  //设置取消点

6.pthread_self(void) //获取线程id号

7.pthread_equal(pthread_t tid1,pthread_t tid2); //比较两个线程的id号,相等返回0,失败返回非0

 

8.线程退出时可以调用安排好的退出清理程序(类似于atexit)

void pthread_cleanup_push(void (*rtn)(void *),void *arg);  //将清理程序入栈(清理程序安装)

    //execute为0弹出不执行 非0弹出并执行

  void pthread_cleanup_pop(int execute);   //这两个函数成对出现,pop()可以写在return后面不执行,但必须要写

注:当执行以下动作时调用清理函数

   ①.调用pthread_exit

   ②.响应取消请求

  ③.execute非零调用pop

9. int pthread_detach(pthread_t tid);[A2]   //如果不关心线程返回状态,可以使线程进入分离状态,分离的线程退出时,底层资源会立即回收,不需要再调用pthread_join()来回收资源,

10.线程属性

线程的分离状态属性可以用函数pthread_detach()函数来代替

线程的栈未尾警戒缓冲区大小

线程栈最低地址

线程栈大小:当有多个线程高并发时需要设置该属性

  指定stack大小不能小于  #define PTHREAD_STACK_MIN   16384  

  int pthread_attr_getstack(const pthread_attr_t *attr,void **stackaddr,void*size);

  int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,int size);//设置栈大小,但需要自己申请一块未使用的空间

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);//设置栈大小,系统自动分配空间

11.pthread_once() //在多线程中保证某件事情只被执行一次

  初始化变量

  pthread_once_t one=PTHREAD_ONCE_INIT;

  //在线程的启动例程中调用,无论哪个线程执行,都只会执行一次

  pthread_once(&one,onceEvent); //onecEvent为需要执行一次的函数,用户自己写

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1. 线程标识:

(1) 比较两个线程ID;

#include <pthread.h>

int pthread_equal(pthread_t tid1, pthread_t tid2);

ret-若相等则返回非0值,否则返回0值

 

(2) 获取线程自身ID;

#include <pthread.h>

pthread_t pthread_self(void);

ret-调用线程的线程ID

 

2. 线程的创建:

#include <pthread.h>

int pthread_create(pthread_t *restrict tidp, //返回线程的ID

         const pthread_attr_t *restrict attr, //线程属性,默认为NULL

                  void *(*start_rtn)(void), //线程函数入口地址

                  void *restrict arg); //参数

ret-成功返回0 失败返回错误编号

 

3. 线程的终止:

(1) 线程只是从启动例程中返回,返回值是线程的退出码;

(2) 线程可以被同一例程中的其他线程取消;

(3) 线程调用pthread_exit。

#include <pthread.h>

void pthread_exit(void *rval_ptr);

rval_ptr是一个无类型指针,与传递给启动例程的单个参数类似,进程中的其他线程可以通过调用pthread_join函数访问到这个指针;

#include <pthread.h>

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

ret-成功返回0 否则返回错误编号

调用线程一直阻塞,直到指定的线程调用pthread_exit,从启动例程中返回或者被取消;   如果线程只是从它的启动例程中返回,rval_ptr将包含返回码;如果线程被取消,由rval_ptr指定的内存单元就设置为PTHREAD_CANCELED.

如果线程已经处于分离状态,pthread_t就会调用失败,返回EINVAL。

如果对线程的返回值不感兴趣,可以吧rval_prt设置为NULL。这种情况下,调用pthread_join将等待线程终止,但不获取线程的终止状态。

 

4. 线程取消:

#include <pthread.h>

int pthread_cancel(pthread_t tid);

ret-成功返回0 失败返回错误码

函数使得由tid标识的线程行为表现为如果调用了参数是PTHREAD_CANCELD的pthread_exit函数,但是,线程可以选择忽略取消方式或者是控制取消方式。函数并不等待线程终止,它仅仅是提出请求;

 

5. 线程清理处理函数:

#include <pthread.h>

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

void pthread_cleanup_pop(int execute); //调用删除上次push的清理程序

当线程执行以下动作时调用清理函数,调用者参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push来安排的。

a. 调用pthread_exit;

b. 想用取消请求;

c. 用非零的execute参数调用pthread_cleanup_pop;

如果execute=0则函数不被调用;

注意正常从线程返回的时候,不会调用该清理函数;

 

C语言多线程pthread库相关函数说明

线程相关操作说明

一、 pthread_t

  pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:

  typedef unsigned long int pthread_t;[A3] 

它是一个线程的标识符。

 

二、 pthread_create

  函数pthread_create用来创建一个线程,它的原型为:

  extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,

  void *(*__start_routine) (void *), void *__arg));

  第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAINEINVAL.前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。

 

三、 pthread_join pthread_exit

  函数pthread_join用来等待一个线程的结束。函数原型为:

  extern int pthread_join __P ((pthread_t __th, void **__thread_return));

  第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:

  extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));

  唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给 thread_return. 最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH.

  在这一节里,我们编写了一个最简单的线程,并掌握了最常用的三个函数pthread_create,pthread_join和pthread_exit.下面,我们来了解线程的一些常用属性以及如何设置这些属性。

  互斥锁相关

  互斥锁用来保证一段时间内只有一个线程在执行一段代码。

  一 pthread_mutex_init

  函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如果需要声明特定属性的互斥锁,须调用函数 pthread_mutexattr_init.函数    pthread_mutexattr_setpshared和函数 pthread_mutexattr_settype用来设置互斥锁属性。前一个函数设置属性pshared,它有两个取值,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进程中的线程同步,后者用于同步本进程的不同线程。在上面的例子中,我们使用的是默认属性PTHREAD_PROCESS_ PRIVATE.后者用来设置互斥锁类型,可选的类型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、 PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT.它们分别定义了不同的上所、解锁机制,一般情况下,选用最后一个默认属性。

二 pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

  pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直至调用pthread_mutex_unlock为止,均被上锁,即同一时间只能被一个线程调用执行。当一个线程执行到pthread_mutex_lock处时,如果该锁此时被另一个线程使用,那此线程被阻塞,即程序将等待到另一个线程释放此互斥锁。

  下面先来一个实例。我们通过创建两个线程来实现对一个数的递加。

  view source

  #include

  #include

  #include

  #include

  #define MAX 10

  pthread_t thread[2];

  pthread_mutex_t mut;

   int number=0, i;

   void *thread1()

   {

   printf ("thread1 : I'm thread 1\n");

  for (i = 0; i < MAX; i++)

  {

   printf("thread1 : number = %d\n",number);

   pthread_mutex_lock(&mut);

   number++;

  pthread_mutex_unlock(&mut);

  sleep(2);

   }

   printf("thread1 :主函数在等我完成任务吗?\n");

  pthread_exit(NULL);

  }

   void *thread2()

   {

   printf("thread2 : I'm thread 2\n");

  for (i = 0; i < MAX; i++)

   {

  printf("thread2 : number = %d\n",number);[nextpage]

   pthread_mutex_lock(&mut);

   number++;

   pthread_mutex_unlock(&mut);

  sleep(3);

  }

  printf("thread2 :主函数在等我完成任务吗?\n");

  pthread_exit(NULL);

  }

  void thread_create(void)

  {

  int temp;

  memset(&thread, 0, sizeof(thread)); //comment1

  /*创建线程*/

  if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2

  printf("线程1创建失败!\n");

  else

  printf("线程1被创建\n");

  if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3

  printf("线程2创建失败");

  else

  printf("线程2被创建\n");

  }

  void thread_wait(void)

  {

  /*等待线程结束*/

  if(thread[0] !=0) { //comment4

  pthread_join(thread[0],NULL);

  printf("线程1已经结束\n");

  }

  if(thread[1] !=0) { //comment5

  pthread_join(thread[1],NULL);

  printf("线程2已经结束\n");

  }

  }

  int main()

  {

  /*用默认属性初始化互斥锁*/

  pthread_mutex_init(&mut,NULL);

  printf("我是主函数哦,我正在创建线程,呵呵\n");

  thread_create();

  printf("我是主函数哦,我正在等待线程完成任务阿,呵呵\n");

  thread_wait();

  return 0;

  }

  下面我们先来编译、执行一下

  引文:

  falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c

  falcon@falcon:~/program/c/code/ftp$ ./thread_example

 

  我是主函数哦,我正在创建线程,呵呵

  线程1被创建

  线程2被创建

  我是主函数哦,我正在等待线程完成任务阿,呵呵

  thread1 : I'm thread 1

  thread1 : number = 0

  thread2 : I'm thread 2

  thread2 : number = 1

  thread1 : number = 2

  thread2 : number = 3

  thread1 : number = 4

  thread2 : number = 5

  thread1 : number = 6

  thread1 : number = 7

  thread2 : number = 8

  thread1 : number = 9

  thread2 : number = 10

  thread1 :主函数在等我完成任务吗?

  线程1已经结束

  thread2 :主函数在等我完成任务吗?

  线程2已经结束

 

转自:https://www.cnblogs.com/edan/p/8945518.html

posted @ 2020-09-11 15:28  陈木  阅读(330)  评论(0)    收藏  举报