一,线程控制图
主线程<——>|工作队列 |<—-> 工作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函数