• Linux 线程与线程同步


    目录

    线程类型

    相关操作函数

    创建线程

    线程退出

    数据回收

    线程分离  

    线程取消 

    获取当前线程ID函数 

     线程比较函数

    线程同步 

    互斥锁

    条件变量


    线程类型

    pthread_t

    每一个线程都有一个唯一的线程 ID,ID 类型为 pthread_t,这个 ID 是一个无符号长整形数,如果想要得到当前线程的线程 ID,可以调用如下函数:

    win32 : 线程ID类型为 HANDLE

    相关操作函数

    头文件  #include

    动态库 libpthread.so 

    创建线程


    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                       void *(*start_routine) (void *), void *arg);

    参数:

    thread: 传出参数,是无符号长整形数,线程创建成功,会将线程 ID 写入到这个指针指向的内存中

    attr: 线程的属性,一般情况下使用默认属性即可,写 NULL

    start_routine: 函数指针,创建出的子线程的处理动作,也就是该函数在子线程中执行。

    arg: 作为实参传递到 start_routine 指针指向的函数内部

    返回值:线程创建成功返回 0,创建失败返回对应的错误号

    win32:CreateThread_beginthreadex

    详见 (1条消息) Window下线程与线程同步总结_陈子青 - See的博客-CSDN博客 

    线程退出

    这是一个阻塞函数, 子线程在运行这个函数就阻塞
    子线程退出, 函数解除阻塞, 回收对应的子线程资源, 类似于回收进程使用的函数 wait()
    int pthread_join(pthread_t thread, void **retval);

    参数:

    thread: 要被回收的子线程的线程 ID

    retval: 二级指针,指向一级指针的地址,是一个传出参数,这个地址中存储了 pthread_exit () 传递出的数据,如果不需要这个参数,可以指定为 NULL

    返回值:线程回收成功返回 0,回收失败返回错误号。

    win32:WaitForSingleObject  

    只要调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用。


    void pthread_exit(void *retval);
    参数:线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为 NULL

     win32 :ExitThread 

    数据回收

    当使用pthread_exit结束线程时,参数可传出需要返回给主线程的数据,主线程使用pthread_join等待线程结束时,参数二可获得传出数据。

    例程如下:

    1. int count =0;
    2. void * pthread(void * arg)
    3. {
    4. while(1)
    5. {
    6. count++;
    7. if(count == 100) pthread_exit(&count);
    8. }
    9. }
    10. int main() {
    11. pthread_t t1;
    12. pthread_create(&t1,NULL,pthread,NULL);
    13. void * arg =NULL;
    14. pthread_join(t1,&arg);
    15. std::cout<<*(int*)arg<
    16. return 0;
    17. }


    线程分离  

    在线程库函数中为我们提供了线程分离函数 pthread_detach(),调用这个函数之后指定的子线程就可以和主线程分离,当子线程退出的时候,其占用的内核资源就被系统的其他进程接管并回收了。线程分离之后在主线程中使用 pthread_join() 就回收不到子线程资源了。
    int pthread_detach(pthread_t thread);

    线程取消 

    线程取消的意思就是在某些特定情况下在一个线程中杀死另一个线程。使用这个函数杀死一个线程需要分两步:

    在线程 A 中调用线程取消函数 pthread_cancel,指定杀死线程 B,这时候线程 B 是死不了的
    在线程 B 中进程一次系统调用(从用户区切换到内核区),否则线程 B 可以一直运行。


    int pthread_cancel(pthread_t thread);
    参数:要杀死的线程的线程 ID
    返回值:函数调用成功返回 0,调用失败返回非 0 错误号。

    获取当前线程ID函数 

    pthread_t pthread_self (void);

    功能:获取当前调用线程的线程ID。

    返回值:当前线程的线程ID标识。

     线程比较函数

    Linux 下线程ID的类型为无符号长整形,为了统一比较标准,提供了判断线程是否相同的函数,功能:判断两个线程ID是否是同一个。

    int pthread_equal (pthread_t thread1, pthread_t thread2);

    形参:thread1是要比较的线程的标识符ID1;thread2是要比较的线程的标识符ID2。

    返回值:不相等返回0,相等非零。

    线程同步 

    互斥锁

    -类型

    pthread_mutex_t  mutex;

    -初始化与销毁

    // 初始化互斥锁
    // restrict: 是一个关键字, 用来修饰指针, 只有这个关键字修饰的指针可以访问指向的内存地址, 其他指针是不行的


    int pthread_mutex_init(pthread_mutex_t *restrict mutex,
               const pthread_mutexattr_t *restrict attr);


    // 释放互斥锁资源            
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    参数:
    mutex: 互斥锁变量的地址
    attr: 互斥锁的属性,一般使用默认属性即可,这个参数指定为 NULL

    -加锁 

    int pthread_mutex_lock(pthread_mutex_t *mutex);

     -解锁

    int pthread_mutex_unlock(pthread_mutex_t *mutex);

    win32 : CreateMutex -  WaitForSingleObject -ReleaseMutex -[互斥对象类型 HANDLE]

    条件变量

    类型-pthread_cond_t cond;

    初始化与销毁

    pthread_cond_t cond;
    // 初始化
    int pthread_cond_init(pthread_cond_t *restrict cond,
          const pthread_condattr_t *restrict attr);


    // 销毁释放资源        
    int pthread_cond_destroy(pthread_cond_t *cond);

    参数:

    cond: 条件变量的地址

    attr: 条件变量属性,一般使用默认属性,指定为 NULL

    阻塞函数

    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); 

    唤醒函数

    // 唤醒阻塞在条件变量上的线程, 至少有一个被解除阻塞
    int pthread_cond_signal(pthread_cond_t *cond);
    // 唤醒阻塞在条件变量上的线程, 被阻塞的线程全部解除阻塞
    int pthread_cond_broadcast(pthread_cond_t *cond);

    win32:CreateEvent SetEvent ResetEvent 

  • 相关阅读:
    【车载Android】模拟Android系统的高负载环境
    Vue 面试题:了解 Vue 中的 Mixin 吗?
    Spring IOC源码:obtainFreshBeanFactory 详解(下)
    ESP8266-Arduino编程实例-LIS2DH 三轴线性加速度计驱动
    初识华为云数据库GaussDB for openGauss
    Effective C++条款11:在operator=中处理“自我赋值”(Handle assignment to self in operator=)
    skywalking部署
    ShardingSphere-proxy-5.0.0部署之分表实现(一)
    常见APP攻击方法 以及防御方法介绍(移动安全)
    树状数组的区间修改
  • 原文地址:https://blog.csdn.net/weixin_40582034/article/details/126521629