1.线程创建

#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会被设置成tidp指向的内润单元;
attr:用于定制各种不同的线程属性,不用的时候设置为NULL,创建一个具有默认属性的线程;
start_rtn:新创建的线程从start_rtn函数的地址开始运行;
arg:如果start_rtn函数传递的参数有一个以上,那么需要把这些参数放在一个结构中,然后把这个结构的地址作为arg参数传入;

线程创建时,并不能保证哪个线程会先运行。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
#include <pthread.h>

pthread_t ntid;

void printfs(const char *s)
{
  pid_t pid;
  pthread_t tid;

  pid = getpid();
  tid = pthread_self();  //获取当前线程的ID
  printf("%s pid %lu tid %lu (0x%1x) \n", s,(unsigned long) pid, (unsigned long)tid, (unsigned long)tid);  
}

void *thr_fn(void *arg)
{
  printfs("new thread:");
  return((void *) 0);
}

int main(void)
{
  int err;
  err = pthread_create(&ntid, NULL, thr_fn, NULL);
  if(err != 0)
       err_exit(err, "can't create thread");
  printfs("main thread:"); 
  sleep(1); 
  exit(0);    
}

以上例程有两个需要注意的点:

  • 需要特别注意主线程和新线程的竞争(线程创建时,并不能保证哪个线程会先运行),所以目前这里采用的主线程休眠一秒,如果主线程不休眠,并且是主线程先运行,那么久会直接exit,新线程就没有运行的机会
  • 新线程是通过pthread_self来获取自己的线程ID。而不是通过ntid。因为主线程通过pthread_create创建新线程,会把新线程的ID存在放第一个参数也就是ntid上。但是新建的线程并不能安全的使用它。理由是:如果新线程在主线程调用pthread_create返回之前就运行了。那么新线程看到的是未初始化的ntid内容,这个内容并不是正确的线程ID。

导致以上两个特别需要注意的原因都是线程创建时,并不能保证哪个线程会先运行。

2.线程终止

如果进程中的任意线程调用了exit、_Exit或者_exit,那么整个进程就会终止。

 

单个线程在不终止整个进程的情况下可以通过三种方式退出:

  • 线程可以简单地从启动例程中返回(函数运行结束退出),返回值是线程的退出码(return)。
  • 线程可以被同一进程中的其他线程取消。
  • 线程调用pthread_exit。

 

#include <pthread.h>

void pthread_exit(void *rval_ptr);

rval_ptr参数是一个无类型指针,就是一个返回值。进程中的其他线程也可以通过调用pthread_join函数访问到这个指针。

int pthread_join(pthread_t thread, void **rval_ptr);
返回值: 成功:0; 失败:返回错误编号
调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
如果线程简单地从它的启动例程返回,pval_ptr就包含返回码。如果线程被取消,由rval_ptr指定的内存单元就设置为PTHREAD_CANCELED.
可以通过调用pthread_join自动把线程置于分离一个状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回einval。

 

可以看到,当一个线程通过调用pthread_exit退出或者简单从启动例程中返回时,进程中的其他线程可以通过使用pthread_join函数获得该线程的退出状态。

pthread_create和pthrad_exit函数的无类型指针参数可以传递的值不止一个,这个指针可以传递包含复杂信息的结构的地址。但是注意,这个结构所使用的内存在调用者完成调用以后必须仍然有效。例如:在调用线程的栈上分配了该结构,那么其他的线程在使用这个结果的时候内存内容可能已经改变了。又比如:线程在自己的栈上分配了一个结构,然后把指向这个结构的指针传给pthread_exit,那么调用pthread_join的线程试图使用该结构时,这个栈有可能已经被撤销。

 

 

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄