前言
以下:
概述
1.基础
2.代码演示
3.练习
4.分析题
1.基础
一、线程基础概念
并发执行原理
通过时间片轮转实现多任务"并行"效果
实际为CPU快速切换执行不同线程
线程 vs 进程
线程共享进程地址空间,切换开销更小
进程拥有独立资源,隔离性更强
二、线程操作函数
1. 线程创建
int pthread_create(
pthread_t *id, // 线程ID存储地址
const pthread_attr_t *attr, // 属性(NULL为默认)
void *(*callback)(void*), // 线程函数
void *arg // 传递给线程的参数
);
返回值:成功返回0,失败返回错误码
示例:
pthread_t tid;
int ret = pthread_create(&tid, NULL, thread_func, NULL);
2. 线程终止
void pthread_exit(void *retval); // 线程主动退出
注意:
与
exit()
不同,仅终止当前线程retval
可被其他线程通过pthread_join()
获取
3. 线程回收
int pthread_join(pthread_t id, void **retval);
功能:阻塞调用线程,直到目标线程结束
参数:
id
:要等待的线程IDretval
:接收线程返回值(二级指针)
三、线程控制
1. 线程属性管理
函数 | 功能 |
---|---|
pthread_self() |
获取当前线程ID |
pthread_detach(id) |
设置线程为分离态(不可join) |
pthread_cancel(id) |
向线程发送取消请求 |
2. 取消状态控制
// 设置取消状态
// 设置取消类型
pthread_setcanceltype(
PTHREAD_CANCEL_DEFERRED, // 延迟取消(默认)
PTHREAD_CANCEL_ASYNCHRONOUS, // 立即取消
NULL
);
延迟取消:只在取消点(如
sleep()
,printf()
)响应取消请求立即取消:随时可能被终止(危险)
四、关键示例
1. 基础线程示例
void* print_msg(void *arg) {
printf("Thread ID: %lu\n", pthread_self());
pthread_exit(NULL);
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, print_msg, NULL);
pthread_join(tid, NULL);
return 0;
}
2. 取消请求处理
void* worker(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while(1) {
printf("Working...\n");
sleep(1); // 取消点
}
return NULL;
}
五、注意事项
分离态线程
设置
pthread_detach()
后:不能调用
pthread_join()
线程结束后自动释放资源
线程安全
共享数据需通过互斥锁(
pthread_mutex_t
)保护避免使用全局变量
错误处理
所有pthread函数返回0表示成功,非0为错误码
建议用
strerror(errno)
输出错误信息
2.代码演示
2.1 pthread_create
#include <IO_head.h>
//分支线程
void* callback(void* arg){
while(1){
printf("division\n");
sleep(1);
}
return NULL;
}
int main(int argc,const char* argv[]){
pthread_t thread_id;
if(pthread_create(&thread_id, NULL, callback, NULL)!=0){
printf("error\n");
}else{
printf("create succeeded\n");
}
//主线程
while(1){
printf("main\n");
sleep(1);
}
return 0;
}
ubuntu@ubuntu:~/IO/class3$ cd ~/IO/class4
ubuntu@ubuntu:~/IO/class4$ ./05_thread
create succeeded
main
division
main
division
main
division
2.2
#include <IO_head.h>
//分支线程
void* callback(void* arg){
static int a =200;
//important
*(int**)arg = &a;
return NULL;
}
int main(int argc,const char* argv[]){
pthread_t thread_id;
int* p = NULL;
if(pthread_create(&thread_id, NULL, callback, &p)!=0){
printf("error\n");
}else{
printf("create succeeded\n");
}
//主线程
sleep(1);
printf("%d\n",*p);
return 0;
}
ubuntu@ubuntu:~/IO/class4$ ./06_pointer
create succeeded
200
2.3
#include <IO_head.h>
//分支线程
void* callback(void* arg){
//分支线程id
printf("division thread id = %ld\n", pthread_self());
static int num =200;
//important
pthread_exit(&num);
return NULL;
}
int main(int argc,const char* argv[]){
pthread_t thread_id;
if(pthread_create(&thread_id, NULL, callback, NULL)!=0){
printf("error\n");
}else{
printf("create succeeded\n");
}
//主线程
//主线程id
printf("main thread id = %ld\n", pthread_self());
int* p = NULL;
pthread_join(thread_id,(void**)&p);
printf("main thread:num = %d\n",*p);
return 0;
}
ubuntu@ubuntu:~/IO/class4$ ./07_self_exit_join
create succeeded
main thread id = 139733924939584
division thread id = 139733924935424
main thread:num = 200
3.练习
分段拷贝
#include <IO_head.h>
typedef struct message{
int ori_des;
int new_des;
int len;
}message;
void RD_WR(int start, int end, int ori_des, int new_des){
lseek(ori_des, start, SEEK_SET);
lseek(new_des, start, SEEK_SET);
char buf;
for(int i = start; i<end;++i){
read(ori_des, &buf, 1);
write(new_des, &buf, 1);
}
printf("copy succeeded\n");
}
void* callback(void* arg){
message* mes_p = (message*)arg;
RD_WR(mes_p->len/2, mes_p->len, mes_p->ori_des, mes_p->new_des);
pthread_exit(NULL);
return NULL;
}
int main(int argc, const char* argv[]){
//文件IO:文件描述符
int file_ori_des = open("./01_vfork.c",O_RDONLY);
int file_new_des = open("./01_new_vfork.c",O_WRONLY|O_CREAT|O_TRUNC,0777);
int len = lseek(file_ori_des,0,SEEK_END);
message message_next = {
.ori_des = file_ori_des,
.new_des = file_new_des,
.len = len
};
pthread_t thread_id;
if(pthread_create(&thread_id,NULL,callback,&message_next)!=0){
printf("error\n");
}else{NULL;}
pthread_join(thread_id,NULL);
RD_WR(0, len/2, file_ori_des, file_new_des);
return 0;
}
4.分析题
4.1解读代码:
结果:
...process1
...process
4.2
for(int i=0;i<3;i++)
{
fork()
printf("-")
}
运行14次
结语
以上