I/O 线程 7.3

发布于:2025-07-04 ⋅ 阅读:(22) ⋅ 点赞:(0)

前言

        以下:

概述

        1.基础

        2.代码演示

        3.练习

        4.分析题

1.基础

一、线程基础概念

  1. 并发执行原理

    • 通过时间片轮转实现多任务"并行"效果

    • 实际为CPU快速切换执行不同线程

  2. 线程 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;
}


五、注意事项

  1. 分离态线程

    • 设置pthread_detach()后:

      • 不能调用pthread_join()

      • 线程结束后自动释放资源

  2. 线程安全

    • 共享数据需通过互斥锁(pthread_mutex_t)保护

    • 避免使用全局变量

  3. 错误处理

    • 所有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次

结语

        以上


网站公告

今日签到

点亮在社区的每一天
去签到