线程

作者: arkliu | 来源:发表于2022-11-28 09:21 被阅读0次

线程间共享全局变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

int var = 100;
void* tfn() {
    var = 200;
    printf("thread\n");
    return NULL;
}

int main() {
    printf("before thread var = %d\n", var);

    pthread_t tid;
    pthread_create(&tid, NULL, &tfn, NULL);
    sleep(1);
    printf("after thread var = %d\n", var);
    return 0;
}

gcc thread.c -pthread -o mythread


image.png

pthread_exit 退出线程

#include <pthread.h>
void pthread_exit(void *retval);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void* tfn() {
    printf("thread\n");
    pthread_exit(NULL); // 退出当前线程
    return NULL;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, &tfn, NULL);
    sleep(1);
    return 0;
}

pthread_join

pthread_join,阻塞等待线程退出,获取线程退出状态。回收线程资源。

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

成功返回0,失败返回错误码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

struct Person{
    int age;
    char name[512];
};

void* tfn() {
    printf("thread\n");
    struct Person* person;
    person = malloc(sizeof(struct Person));
    bzero(person,sizeof(struct Person));
    person->age = 22;
    strcpy(person->name, "张三");
    pthread_exit( (void *)person);
}

int main() {
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, &tfn, NULL);
    if (ret !=0) 
    {
        perror("pthread_create error");
        exit(1);
    }
    
    struct Person *retPerson;
    ret = pthread_join(tid, (void **)&retPerson); // pthread_join回收资源,获取线程退出值
    if (ret !=0) 
    {
        perror("pthread_join error");
        exit(1);
    }
    printf("age = %d, name = %s\n",retPerson->age, retPerson->name);
    pthread_exit(NULL);
}

1669604681753.png

pthread_cancel

#include <pthread.h>
int pthread_cancel(pthread_t thread);

pthread_cancel用来杀死取消线程,注意,线程的取消并不是实时的,需要等待线程达到某个取消点。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

void* tfn() {
    while (1)
    {
        printf("thread pid=%d, tid=%lu\n",getpid(),pthread_self());
        sleep(1);
    pthread_testcancel();//自己添加一个取消点
    }
    return (void *)NULL;
}

int main() {
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, &tfn, NULL);
    if (ret !=0) 
    {
        perror("pthread_create error");
        exit(1);
    }
    
    sleep(5);
    pthread_cancel(tid);
    while(1);
}

1669607622471.png

线程分离

线程的分离状态决定一个线程以什么样的方式来终止自己。

  • 非分离状态:线程的默认属性是非分离状态,这种情况下,原有的线程等待创建的线程结束,只有当pthread_join返回时,创建的线程才算终止,才能释放自己占用的系统资源。
  • 分离状态: 分离线程自己运行结束了,线程也就终止了。会自动释放系统资源。

pthread_detach线程分离

#include <pthread.h>
int pthread_detach(pthread_t thread);

pthread_detach实现线程分离,线程主动与主控线程断开关系,线程退出后,其退出状态不由其他线程获取,而是直接自己自动释放资源。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

void* tfn() {
    printf("thread pid=%d, tid=%lu\n",getpid(),pthread_self());
    return (void *)NULL;
}

int main() {
    pthread_t tid;
    int ret = pthread_create(&tid, NULL, &tfn, NULL);
    if (ret !=0) 
    {
        perror("pthread_create error");
        exit(1);
    }
    
    pthread_detach(tid); // 设置线程分离,线程终止会自动清理pcb,无需回收
    sleep(5);
}

使用线程属性设置分离线程

线程属性相关api

#include <pthread.h>
初始化线程属性
int pthread_attr_init(pthread_attr_t *attr);

销毁线程属性所占用的资源
int pthread_attr_destroy(pthread_attr_t *attr);

// 设置线程分离属性
PTHREAD_CREATE_DETACHED  分离线程
PTHREAD_CREATE_JOINABLE   非分离线程
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
// 获取线程分离属性
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

void* tfn() {
    printf("thread pid=%d, tid=%lu\n",getpid(),pthread_self());
    return (void *)NULL;
}

int main() {
    pthread_t tid;
    pthread_attr_t attr;
    int ret = pthread_attr_init(&attr);
    if (ret !=0)
    {
        fprintf(stderr, "pthread_attr_init error %s\n", strerror(ret));
        exit(1);
    }
    
    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    ret = pthread_create(&tid, &attr, &tfn, NULL);
    if (ret !=0) 
    {
        perror("pthread_create error");
        exit(1);
    }

    ret = pthread_attr_destroy(&attr);
    if (ret !=0)
    {
        fprintf(stderr, "pthread_attr_destroy error %s\n", strerror(ret));
        exit(1);
    }
    sleep(5);
}

线程屏蔽信号

#include <signal.h>
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include<errno.h>
#include <pthread.h>
#include <signal.h>

void sig_handler(int signo) {
    printf("pthread id in the sig_handler:%lx\n ", pthread_self());
    if (signo == SIGALRM)
    {
        printf("timeout...\n");
    }
    alarm(2);
}

void* th_fn(void *arg) {
    if (signal(SIGALRM, sig_handler) == SIG_ERR)
    {
        perror("signal SIGALRM error...");
    }
    //在子线程中设置定时器,产生的SIGALRM信号发送给主线程
    alarm(2);
    int i;
    for (i = 1; i < 100; i++)
    {
        printf("(%lx) i:%d\n",pthread_self(),i);
        sleep(1);
    }
    
    return (void*)0;
}

int main() {
    pthread_t th;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int ret;
    ret = pthread_create(&th, &attr, th_fn, NULL); 
    if (ret !=0) 
    {
        perror("pthread_create error");
    }

    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGALRM);
    // 对主线程屏蔽SIGALRM信号
    pthread_sigmask(SIG_SETMASK, &set, NULL);

    while (1)
    {
        printf("control thread(%lu) is running\n", pthread_self());
        sleep(10);
    }
    printf("control thread over\n");
    return 0;
}

image.png

相关文章

  • Android

    线程间通信 主线程和工作线程主线程和工作线程 工作线程与工作线程工作线程与工作线程 为什么主线程Looper.lo...

  • 三、操作系统之线程

    前言 什么是线程 引入线程的原因 线程的概念 线程和进程的关系 线程结构 线程有点 多线程模型 用户线程和内核线程...

  • Thread

    队列 线程锁 多线程,线程池 队列 多线程爬虫示例 多线程 自定义线程 线程池

  • 总结多线程与设计模式+synchronized+性能+高吞吐+死

    Java线程 Java语言的线程 何谓线程 线程启动 线程的暂时停止 线程的共享互斥 线程的协调 线程的状态转移 ...

  • 多线程编程

    摘要 线程概念,线程与进程的区别与联系学会线程控制,线程创建,线程终止,线程等待了解线程分离与线程安全学会线程同步...

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java并发之守护线程

    java中有两种线程,用户线程和守护线程用户线程:主线程停止时,用户线程不会停止守护线程:主线程停止时,守护线程也...

  • Java线程池的使用

    线程类型: 固定线程 cached线程 定时线程 固定线程池使用 cache线程池使用 定时调度线程池使用

  • 线程基础知识

    线程学习 线程的基础知识 线程是什么? 线程和进程的关系 线程的6个状态 线程优先级 主线程、多线程、后台线程的概...

  • 多线程介绍

    一、进程与线程 进程介绍 线程介绍 线程的串行 二、多线程 多线程介绍 多线程原理 多线程的优缺点 多线程优点: ...

网友评论

      本文标题:线程

      本文链接:https://www.haomeiwen.com/subject/tfimxdtx.html