首页 > 其他分享 >线程创建的函数及应用小结

线程创建的函数及应用小结

时间:2024-06-02 21:56:47浏览次数:21  
标签:attr int void 线程 pthread tid 小结 函数

进程是计算机分配资源的基本单位,线程是cpu调度的基本单位

线程基本概念:

LWP:light weight process 轻量级的进程。创建线程的底层函数和进程一样,都是clone,因此线程的本质仍是进程(在linux环境下)

与进程相比,线程有独立的TCB结构体(类似于进程的PCB),但没有独立的地址空间(共享),类似于合租与独居。

查看线程号(LWP,不是TID)可以用下述命令:

ps -Lf xxx(PID)

线程创建相关函数

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
//=================================属性设置按需要采用,若普通情况可以不用设置===============//
pthread_attr_t attr;                                // 定义线程的属性变量
int pthread_attr_init(pthread_attr_t *attr);        // 初始化属性变量
int pthread_attr_setXXX(pthread_attr_t *attr, ...); // 设置属性变量的值
//此处仅列举常用的//
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); // 设置/获得线程的分离属性
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); // 设置/获得是否继承创建者的调度策略
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); // 设置/获得调度策略
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param); // 设置/获得线程的静态优先级
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
//=================================上述属性设置按需要采用,若普通情况可以不用设置===============//

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
// 创建线程,此处void *(*start_routine)(void *)函数指针指向的函数,void *arg作为其参数,并且需要采用值传递,如果数据类型不同需要强转
int pthread_detach(pthread_t thread); // 如果没有设置线程的分离属性,可以用此函数强制设为分离属性,防止线程结束后变为僵尸进程,无法释放资源,而且不能再用 pthread_join等待回收该进程的资源

pthread_t pthread_self(void);         // 创建成功后,可以在线程中使用,获取当前线程的tid
void pthread_exit(void *retval);      // 退出线程,并得到返回值retval
int pthread_cancel(pthread_t thread); // 给指定线程发送一个取消的请求
int pthread_setcancelstate(int state, int *oldstate);
// 设置线程的取消状态:PTHREAD_CANCEL_ENABLE 可取消; PTHREAD_CANCEL_DISABLE 不可取消
int pthread_setcanceltype(int type, int *oldtype);
// 设置线程的取消类型:PTHREAD_CANCEL_DEFERRED 延时响应; PTHREAD_CANCEL_ASYNCHRONOUS 立即响应。

int pthread_join(pthread_t thread, void **retval); // 接合指定已结束或者待结束的线程,并得到返回状态值;如果指定的线程还在运行,将会阻塞等待。

应用实例

char *retval = "byebye!\n"; // 假设为共享资源
pthread_mutex_t m;          // 定义互斥锁

void handler(void *arg)
{
    pthread_mutex_unlock(&m);
}

void *child_thread(void *arg)
{

    while (1)
    {
        pthread_cleanup_push(handler, NULL); // 上锁前,需要将handler函数压入线程取消处理的栈中,以防止该子进程在运行的中途被取消,造成死锁
        pthread_mutex_lock(&m);
        printf("Child thread obtain the mutex:%s\n", retval);
        pthread_mutex_unlock(&m);
        pthread_cleanup_pop(0); // 解锁后,将handler从栈中弹出,不执行
        sleep(2);
    }
}

int main()
{
    pthread_mutex_init(&m, NULL);

    pthread_t tidofparent = pthread_self(); // 接收主线程的tid值。
    printf("parent's tid:%ld\n", tidofparent);
    printf("parent's tid:%ld\n", sizeof(int));

    pthread_t tid;
    pthread_create(&tid, NULL, child_thread, NULL); // 新建子线程
    // pthread_detach(tid); 让线程“自立门户”,结束后资源自动回收,此处与pthread_cancel和pthread_join冲突,
    sleep(5);
    pthread_cancel(tid); // 5秒后,向子线程发送取消的请求

    // 待子线程被取消后,锁被handler自动释放,可以继续加互斥锁,对公共资源进行操作
    pthread_mutex_lock(&m);
    retval = "I'm main pthread!\n";
    printf("Now I botain the mutex:%s\n", retval);
    pthread_mutex_unlock(&m);
    /*
    void *p;
    pthread_join(tid, &p); // 如果没有采用pthread_cancel(tid)取消子进程,这部分将会阻塞等待子线程结束,接受子线程的返回值并打印
    printf("子线程的返退出回值:%s\n", (char *)p);
*/
    return 0;
}

注意事项

1.主线程退出也可以用pthread_exit(),其他子线程照样运行不受影响。但如果主线程运行了return/exit等语句,或者子线程用exit,会导致整个进程退出。

2.避免线程编程僵尸进程的三种方法:

  • int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) 提前设置分离属性
  • int pthread_detach(pthread_t thread);子线程创建后强制设置分离属性
  • 在线程结束后利用pthread_join()进行接合。

3.malloc 和mmap 申请的内存可以被其他子线程释放,因为申请出来的都是共享堆地址。

4.信号语义复杂,尽量避免和线程机制混用。

标签:attr,int,void,线程,pthread,tid,小结,函数
From: https://www.cnblogs.com/cino/p/18227677

相关文章

  • MySQL注入之Fuzz测试&WAF Bypass小结
    目录BurpSuiteFuzz测试内联注释绕过union[]select联合查询绕过敏感函数绕过from[]information_schema查表报错注入示例常规绕过思路总结空格绕过引号绕过逗号绕过比较符号绕过逻辑符号绕过关键字绕过编码绕过等价函数绕过宽字节注入多参数请求拆分生僻函数输出内容过滤BurpSuite......
  • 20、matlab信号波形生成:狄利克雷函数、高斯脉冲和高斯脉冲序列
    1、狄利克雷函数生成波形diric()函数语法:y=diric(x,n)返回n次的狄利克雷函数对输入数组x的元素求值。1)diric()函数代码x=linspace(-2*pi,2*pi,301);%定义x取值d6=diric(x,6);d7=diric(x,7);subplot(2,1,1)plot(x,d6)ylabel('n=6')title('狄利克雷函数')su......
  • 线程池的实现源码及应用举例
    1.线程池本质​多个线程组成的一个集合,目的为了并发执行任务,定义时是一个结构体,成员有互斥锁,条件变量,任务链队列指针,任务链队列中等待的任务个数,当前活跃的线程数量,线程ID,线程销毁标记等2.线程池的关键技术(1)万能函数指针(通用函数指针):*void*(*p)(voi......
  • C/C++mai函数的参数
    在C和C++编程中,main函数通常是程序的入口点,定义程序的启动方式。函数签名intmain(intargc,constchar**argv,constchar**envp)包括三个参数:argc、argv和envp。这些参数分别用于接收命令行参数和环境变量。1.intargcargc代表“argumentcount”,表示传递给程序的命令行参......
  • Java面试题:解释一下Java中的synchronized关键字,它是如何保证线程安全的?
    在Java中,synchronized关键字是一种同步锁机制,用于确保多个线程在访问共享资源时能够保持线程安全。线程安全是指在多线程环境下,当多个线程尝试同时访问共享资源时,任何时刻最多只有一个线程能够执行特定的代码段。synchronized关键字可以用于以下几个方面:方法同步:当synch......
  • Day21.函数的类型提示
    1.函数的类型提示_函数常规传参2.函数的类型提示_函数参数设置默认值3.函数的类型提示__annotations__方法查看参数传参类型 ......
  • Redis单线程
    Redis是基于Reactor模式开发的网络事件处理器,这个处理器是单线程的,所以redis是单线程的。为什么它是单线程还那么快呢?主要有以下几个原因:一、纯内存操作由于Redis是纯内存操作,相比于磁盘来说,内存就快得多,这个是Redis快的主要原因。二、多路复用I/O机制(NIO)Re......
  • 信号量(Semaphore),事件Event(了解),队列补充,进程池和线程池(重点),协程理论,Greenlet,Gevent模
    Ⅰ信号量(Semaphore)【一】什么是信号量信号量Semahpore(同线程一样)互斥锁:允许在同一时刻只能有一个线程或进程同资源进行修改信号量:允许指定数量的进程或线程对资源进行修改【二】例子比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去......
  • 【JUC】3-用户线程和守护线程
    一般情况下不做特别说明配置,默认都是用户线程 UserThread是系统的工作线程,它会完成这个程序需要完成的业务操作 DaemonThread是一种特殊的线程,为其它线程服务的,在后台默默的完成一些系统性的服务,比如垃圾回收线程就是最典型的例子守护线程作为一个服务线程,没有服务对象......
  • Java高并发核心编程.卷2,多线程、锁、JMM、JUC、高并发设计模式 (尼恩)电子版百度云
    书获取链接:python33  。c o  m我的阅读笔记:多线程:介绍Java多线程的基础概念,如线程的创建、启动、状态转换、线程间通信等。锁:深入探讨Java中的各种锁机制,包括内置锁(synchronized)、ReentrantLock、ReadWriteLock等,以及它们的使用场景和性能特点。Java内存模型(JMM):解释J......