- 线程概述
- 线程的基本概念
- 用户态线程和内核态线程
- 线程管理
- 创建线程
- 结束线程
- 挂起线程
- 线程同步
- 取消线程
- 取消处理程序
- 线程特定数据的处理函数
- 线程属性
2.1 创建线程
线程是用pthread_create动态创建的
#include <pthread.h>
int pthread_create(pthread_t *thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
该函数需要四个参数
- *thread
- pthread_t类型指针,这是新创建的线程的标识符(ID)
- *attr
- pthread_attr_t类型指针,指定新线程的属性,如果为NULL,则使用默认的属性,即使用最小的对战空间,也使用通常的调度策略
- *start_routine
- void类型指针,需强制类型转换,如(void *)(&fun1)。是一个函数的地址,表示新线程将从该函数开始运行,也就是新线程的开始运行的地址
- *arg
- void类型指针,需要强制类型转换,如(void *)( *i)函数start_routine需要的参数
返回类型
pthread_create 执行成功,返回0,并且将新创建的线程的进程标识符存放在由指针thread指向的地址,如果执行失败,返回一个非零值
与创建新进程区别
与创建新进程不同的是,新创建的线程并不是和父进程和同一时间开始运行的,而是从start_routine函数开始运行,因为一个父进程的子线程们是共享父进程的资源和地址空间的,所以如果同时运行,则所有的子进程都将同时使用同一资源和地址空间,出错
线程ID
调用pthread_self()函数得到线程的ID
#include <pthread.h>
pthread_t pthread_self();
2.2 结束线程
2.1中创建的新线程可以通过pthread_exit来终止,或者当函数start_routine返回时自然终止。
pthread_exit函数定义如下:
#include <pthread.h>
void pthread_exit(void *retval);
pthread_exit成功调用时返回0,失败时返回-1
实例代码
#include <stddef.h>
#include <stdio.h>
#include <unistd.h> //sleep()函数需要的头文件
#include <pthread.h>
void print_message(char *ptr);
int main()
{
pthread_t thread1, thread2;
char *msg1="Hello\n";
char *msg2="World\n";
pthread_create(&thread1, NULL, (void*)(&print_message), (void*)msg1);
pthread_create(&thread2, NULL, (void*)(&print_message), (void*)msg2);
sleep(1); //单位为毫秒
return 0;
}
void print_message(char *ptr)
{
int retval;
printf("Thread ID:%lx", pthread_self());
printf("%s", ptr);
pthread_exit(&retval);
}
sleep和wait区别
- sleep()
- 指线程被调用时,占着CPU不工作,形象地说明为“占着CPU睡觉”,此时,系统的CPU部分资源被占用,其他线程无法进入,会增加时间限制。
- wait
- 指线程处于进入等待状态,形象地说明为“等待使用CPU”,此时线程不占用任何资源,不增加时间限制。
所以
- 指线程处于进入等待状态,形象地说明为“等待使用CPU”,此时线程不占用任何资源,不增加时间限制。
- sleep(100L)意思为:占用CPU,线程休眠100毫秒
wait (100L) 意思为:不占用CPU,线程等待100毫秒
部分代码分析
pthread_create(&thread1, NULL, (void*)(&print_message), (void*)msg1);
因为第一个参数需要的线程ID号的指针,所以为&thread1;第二个参数使用NULL为默认类型;第三个参数需要指向void类型的指针,因此强制类型转换(void*)(&print_message);第四个参数需要指向void类型的指针参数,因此也进行强制类型转换(void*)msg1。