前言
以下:
概述
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
:要等待的线程ID -
retval
:接收线程返回值(二级指针)
-
三、线程控制
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){//分支线程idprintf("division thread id = %ld\n", pthread_self());static int num =200;//importantpthread_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");}//主线程//主线程idprintf("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次
结语
以上