当前位置: 首页 > news >正文

sylar--线程模块

 本模块是基于pthread实现的。自己封装了pthread,并提供信号量、互斥锁、读写锁和自旋锁。

线程模块定义的类

class Semaphore:封装了信号量

class Mutex:封装了互斥锁

class RWMutex:封装了读写锁

class SpinLock:封装了自旋锁

class Thread:封装了线程pthread

对于上述相关的信号量和锁,如果没有调用对应init函数进行初始化,任何尝试使用相关信号量和锁的的行为,都是未定义的

在调用destroy之前,应该确保没有线程在使用,否则destroy是未定义行为

互斥锁与自旋锁的区别?

互斥锁,是sleep-waiting类型的锁。需要消耗大量的系统资源来建立锁。当线程被阻塞时,线程的调度状态被修改,线程被加入等待队列。当锁可用是,获取锁之前,线程将从等待队列取出并更改其调度状态。在阻塞期间,不消耗CPU资源

互斥锁适用于可能会被阻塞很长时间的场景

自旋锁,是busy-waiting类型的锁。需要消耗很少的系统资源建立锁。spinlock不会使线程进入睡眠状态,但会一直消耗CPU时间

自旋锁适用于仅需要阻塞很短时间的场景

class Semaphore

成员变量

private:sem_t m_semaphore;     //信号量,是一个长整型数

成员函数

  • Semaphore(uint32_t count = 0):初始化信号量,调用sem_init实现
  • ~Semaphore():销毁信号量,调用sem_destroy实现
  • void wait():获取信号量,调用sem_wait实现
  • void notify():释放信号量,调用sem_post实现
  • int sem_init(sem_t *sem, int pshared, unsigned int value)

        sem是指向要初始化的信号量的指针

        pshared指定信号量是进程内共享(0)还是跨进程共享(~0)

        value是信号量的初始值

        成功返回0,否则返回-1

  • int sem_destroy(sem_t *sem)

        确保没有任何线程或进程正在使用信号量,才能调用此函数,否则会导致未定义行为

  • int sem_wait(sem_t *sem)

        sem是指向要获取的信号量的指针。若调用时信号量的值大于0,则递减该值并立即返回,否则当前线程被阻塞

  • int sem_post(sem_t *sem)

        用于向指定的命名或未命名信号量发送信号,使其计数器+1。若有线程在等待,则将其中一个唤醒。成功返回0,失败返回-1并设置errno

private:Semaphore(const Semaphore&) = delete;              //禁止拷贝构造Semaphore(const Semaphore&&) = delete;             //禁止移动构造Semaphore& operator=(const Semaphore&) = delete;   //禁止拷贝赋值

上述三个函数,通过private+delete,来明确禁止信号量对象的拷贝和移动操作。

信号量通常包含操作系统资源,拷贝会导致资源管理混乱

移动后原对象和新对象的资源句柄可能同时有效,导致未定义行为

class Mutex

成员变量

private:pthread_mutex_t m_mutex;        //互斥锁

成员函数

  • Mutex():初始化互斥锁对象,调用pthread_mutex_init实现
  • ~Mutex():销毁已初始化的互斥锁对象,调用pthread_mutex_destroy实现
  • lock():加锁操作,调用pthread_mutex_lock实现
  • unlock():解锁操作,调用pthread_mutex_unlock实现
  • int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)

        mutex:指向要初始化的互斥锁对象的指针

        attr:指向互斥锁属性对象的指针,置为nullptr会使用默认属性

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_mutex_destroy(pthread_mutex_t *mutex)

        mutex:指向要销毁的互斥锁对象的指针

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_mutex_lock(pthread_mutex_t *mutex)

        mutex:指向要加锁的互斥锁对象的指针

        成功时返回0,失败时返回错误码并设置errno

        当前线程调用此函数时,如果该互斥锁没有被其它线程持有,则会获取该互斥锁并标记为被持有;否则,当前线程被阻塞,直到锁被释放,再重新尝试加锁

  • int pthread_mutex_unlock(pthread_mutex_t *mutex)

        mutex:指向要解锁的互斥锁对象的指针

        成功时返回0,失败时返回错误码并设置errno

        当一个线程调用此函数时,该互斥锁将被标记为未被持有。如果有其它线程在等待该锁,则将其中一个线程唤醒

class RWMetux

成员变量

private:pthread_rwlock_t m_lock;        //读写锁

成员函数

  • RWMutex():初始化一个读写锁对象,调用pthread_rwlock_init实现
  • ~RWMutex():销毁一个读写锁,调用pthread_rwlock_destroy实现
  • rdlock():加读锁,调用pthread_rwlock_rdlock实现
  • wrlock():加写锁,调用pthread_rwlock_wrlock实现
  • unlock():释放锁,调用pthread_rwlock_unlock实现

读写锁是一种同步机制,用于在多线程环境下对共享资源进行访问控制。允许多个进程同时读取共享资源,但只允许一个线程写入共享资源

  • int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)

        rwlock:指向要初始化的读写锁对象的指针

        attr:指向读写锁属性对象的指针,为nullptr时使用默认属性

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)

        rwlock:指向要销毁的读写锁对象的指针

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)

        成功时返回0,失败时返回错误码并设置errno

        允许多个线程同时读取共享资源,但不能写入

        如果有线程持有写锁,其它线程将被阻塞直到写入锁被释放

  • int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)

        成功时返回0,失败时返回错误码并设置errno

        阻止其它线程读取或写入共享资源,直到该线程释放写锁

        调用此函数时,若其它线程持有读锁或写锁,此函数会被阻塞,直到所有读、写锁释放

  • int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)

        成功时返回0,失败时返回错误码并设置errno

class SpinLock

成员变量

private:pthread_spinlock_t m_mutex;   //自旋锁

成员函数

  • Spinlock():初始化自旋锁,调用pthread_spin_init实现
  • ~Spinlock():销毁自旋锁,调用pthread_spin_destroy实现
  • lock():加锁,调用pthread_spin_lock实现
  • unlock():解锁,调用pthread_spin_unlock实现
  • int pthread_spin_init(pthread_spinlock_t *lock, int pshared)

        lock:指向初始化的自旋锁的指针

        pshared:自旋锁是进程内共享(0)还是跨进程共享(~0)

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_spin_destroy(pthread_spinlock_t *lock)

        lock:指向要被销毁的自旋锁的指针

        成功则返回0,失败时返回错误码并设置errno

  • int pthread_spin_lock(pthread_spinlock_t *lock)

        若该锁没有被其它线程持有,则当前线程获取自旋锁,否则阻塞,直到其它线程释放锁

        成功时返回0,失败时返回错误码并设置errno

  • int pthread_spin_unlock(pthread_spinlock_t *lock)

        成功时返回0,失败时返回错误码并设置errno

class Thread

成员变量

private:pid_t m_id = -1;                //线程idpthread_t m_thread = 0;         //线程结构std::function<void()> m_cb;     //线程执行函数std::string m_name;             //线程名称Semaphore m_semaphore;          //信号量

成员函数

  • Thread::Thread(std::function<void()> cb, const std::string &name):初始化线程执行函数、线程名称,通过pthread_create创建新线程
  • Thread::~Thread():检查m_thread是否存在,存在则调用pthread_detach来分离已结束的线程。在析构函数中分离线程,可以避免主线程退出时出现悬挂线程,从而防止内存泄漏
  • void Thread::join():调用pthread_join来实现等待线程执行完成
  • void* Thread::run(void* arg):线程执行函数。通过信号量,在构造函数中创建线程后一直阻塞,直到run方法运行并通知信号量,构造函数才会返回
  • int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)

        thread:指向pthread_t类型的指针,用于返回新线程的id

        attr:指向pthread_attr_t类型的指针,包含新线程属性信息,设置为nullptr使用默认值

        start_routine:指向新线程函数的指针,该函数将在新线程中运行

        arg:指向新线程函数的参数的指针,不需要该参数时,可设置为nullptr

        新线程将在与调用pthread_crreate函数的线程并发执行的情况下运行

  • int pthread_detach(pthread_t thread)

        将指定线程标记为”可分离状态“,被分离的线程终止时,系统自动回收其资源

        线程一旦分离,不能再通过pthread_join等待其结束

        成功时返回0,否则返回错误码并设置errno

  • int pthread_join(pthread_t thread, void **retval)

        thread:到等待的线程id

        retval:指向指针的指针,用于存储线程返回的值。若不需要获取返回值,设置为nullptr

        阻塞机制,用于等待指定线程的终止并获取其返回值,同时回收该线程所使用的资源

        成功时返回0,表示等待线程成功退出

private:Thread(const Thread&) = delete;Thread(const Thread&&) = delete;Thread& operator= (const Thread&) = delete;

 

1、信号量在上述代码中有什么用?

2、Mutex、Spinlock和CSA的性能如何?

3、为什么要在FileLogAppender::Log中周期性reopen?

4、RALL是什么?

5、不能拷贝和移动类对象时,应该怎么做?

6、如何保证在出构造函数之前,确保线程先跑起来?

相关文章:

  • 如何有效删除 iPhone 上的所有内容?
  • 零基础玩转Python生物信息学:数据分析与算法实现
  • SpringBoot(七) --- Redis基础
  • Windows 12确认没了,Win11 重心偏移修Bug
  • Asp.Net Core基于StackExchange Redis 缓存
  • 让视觉基础模型(VFMs)像大语言模型(LLMs)一样“会思考”​
  • Vue2 和 Vue3 常见 CSS 样式归纳总结
  • 09.MySQL内外连接
  • 基于对比学习的带钢表面缺陷分类研究,整合SimCLR自监督预训练与YOLOv8目标检测框架的技术解析及Python实现方案
  • ASP.NET Core 中间件深度解析:构建灵活高效的请求处理管道
  • 【学习笔记】Circuit Tracing: Revealing Computational Graphs in Language Models
  • 电脑网络重置,找不到原先自家的WIFI,手机还能正常连接并上网
  • 【C++】AVL树的概念及实现(万字图文超详解)
  • C++11 中 auto 和 decltype 的深入解析
  • 【Python零基础入门系列】第7篇:Python中的错误与异常处理
  • SPI通信协议(软件SPI读取W25Q64)
  • 计算机视觉处理----OpenCV(从摄像头采集视频、视频处理与视频录制)
  • [特殊字符] 革命性AI提示词优化平台正式开源!
  • 目标检测任务的评估指标mAP50和mAP50-95
  • YOLO12 改进|融入 Mamba 架构:插入视觉状态空间模块 VSS Block 的硬核升级
  • 广州网站改版设计公司/销售新手怎么找客源
  • 北京网站建设还公司/阿里巴巴推广
  • 建立一个购物网站/seo网站推广收费
  • 十堰微网站建设/百度指数大数据
  • 网站建设公司宣传标语/新品怎么推广效果最好
  • 网站关键词的优化在哪做/电商营销的策略与方法