您的位置:首页 > 运维架构 > Linux

LInux的Posix的线程控制

2017-07-04 23:43 197 查看

一,线程控制图

主线程<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3

线程1<——> |工作队列 |<—-> 工作1 <—>工作2 <—>工作3

线程2<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3

线程3<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3

二,线程的标识符

与进程标识符类似,每一个线程都有一个在进程中唯一的线程标识符(线程ID),其用数据类型 pthread_t 来表示的,该数据类型在Linux中其实就是一个无符号长整型数据。

LInux提供了两个函数用于对线程标识符,其标准调用格式说明如下:


#include <pthread.h>
pthread_t pthread_self(void);


pthread_self函数用于获取线程自身的线程标识符,其返回值是线程自身的线程标识符。
pthread_equal函数用于比较两个线程标识符,其标准调用格式说明如下:


#include <pthread.h>
int pthread_equal(pthread_tid, pthread_t tid2);


三,线程控制的相关函数

使用gcc编译多线程程序是, 必须与pthread函数库链接,在终端下编译使用下列 gcc -lpthread

1,pthread_create函数

文档说明

NAME
pthread_create - create a new thread

SYNOPSIS
#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

Compile and link with -pthread.

DESCRIPTION
The  pthread_create()  function  starts  a  new  thread  in the calling
process.  The new thread starts execution by invoking  start_routine();
arg is passed as the sole argument of start_routine().

The new thread terminates in one of the following ways:

* It  calls  pthread_exit(3),  specifying  an exit status value that is
available  to  another  thread  in  the  same  process   that   calls
pthread_join(3).


一个例子

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

pthread_t ntid; //线程id

//打印标识符的函数
void printds(const char *s)
{
pid_t pid; //进程标识符
pthread_t tid;  //线程标识符

pid = getpid(); // 获取进程标识符id
//获取线程标识符的id
tid = pthread_self();

printf("%s pid, %u tid %u (0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);  //打印进程和线程id
}

//线程中开始运行的函数
void *thr_fn(void *arg)
{
printds("new thread:");
return ((void*)0);
}

int main(void)
{
int err;
err = pthread_create(&ntid, NULL, thr_fn, NULL);  //创建一个线程

// 如果出错误打印财务标号
if (err != 0)
{
printf("can't create thread %s\n", strerror(err));
}

//打印主线程号
printds("main thread:");

sleep(1);
exit(0);
return 0;
}




可以看到标识符为7738的进程创建了两个标识符分别为 2274588416和2266298112 的线程。

2,pthread_exit函数

进程可以调用exit系列函数退出当前进程, 线程也可以通过如下3种方式退出, 子啊不终止整个进程的情况下停止线程的控制流

1,线程只是从启动列程种返回,返回值是线程的退出码。

2,线程可以被同一个进程中的其他进程终止。

3,线程调用pthread_exit函数退出

Linux内核提供pthread_exit函数用于主动退出线程, 其在LInux函数库种原型是:

NAME
pthread_exit - terminate calling thread

SYNOPSIS
#include <pthread.h>

void pthread_exit(void *retval);

Compile and link with -pthread.

DESCRIPTION
The pthread_exit() function terminates the calling thread and returns a
value via retval that (if the  thread  is  joinable)  is  available  to
another thread in the same process that calls pthread_join(3).

Any  clean-up handlers established by pthread_cleanup_push(3) that have
not yet been popped, are popped (in the reverse of the order  in  which
they  were pushed) and executed.  If the thread has any thread-specific
data, then, after the clean-up handlers have been executed, the  corre‐
sponding destructor functions are called, in an unspecified order.


3,pthread_join函数 我的理解就是没有pthread_join函数就执行pthread_create函数

如果当一个线程已经执行完成之后, 可以被其他的线程了阻塞挂起,过后等待指定的线程调用pthread_exit,以从启动列程中返回或被取消,LInux内核可以调用pthread_join函数来完成对线程阻塞,其在LInux函数库中的原型是:

NAME
pthread_join - join with a terminated thread

SYNOPSIS
#include <pthread.h>

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

Compile and link with -pthread.

DESCRIPTION
The pthread_join() function waits for the thread specified by thread to
terminate.  If that thread has already terminated, then  pthread_join()
returns immediately.  The thread specified by thread must be joinable.

If  retval  is  not NULL, then pthread_join() copies the exit status of
the target thread (i.e., the value that the target thread  supplied  to
pthread_exit(3))  into the location pointed to by *retval.  If the tar‐
get thread was canceled, then PTHREAD_CANCELED is placed in *retval.

If multiple threads simultaneously try to join with  the  same  thread,


返回:如果调用成功,函数返回0, 反之返回一个非0值

例子:

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

void print_msg(char *ptr);

int main(void)
{
pthread_t thread1, thread2;
int i, j;
void *retval;

char *msg1 = "This is the frist thread\n";
char *msg2 = "This is the second thread\n";

pthread_create(&thread1, NULL, (void *)(&print_msg),(void *)msg1);

pthread_create(&thread2, NULL, (void *)(&print_msg), (void *)msg2);  //创建两个线程

pthread_join(thread1, &retval);
pthread_join(thread2, &retval);
return 0;
}

//打印信息函数, 线程从这个函数开始执行
void print_msg(char *ptr)
{
int i;
for( i = 0; i < 10; i++)
{
//连续输出10个字符串
printf("%s\n", ptr);
}
}


运行效果图



4,pthread_cancel函数



返回:如果操作成功返回0,失败返回对应错误码

5,pthread_cleanup_push和pthread_cleanup_pop函数

当调用pthread_cancel函数取消了一个线程之后,需要调用相应的函数对进程退出之后的环境继续清理,



1,调用pthread_exit函数的时候

2,响应取消请求的时候

3,用非execute参数调用pthread_cleanup_pop的时候

6,pthread_detach函数

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: