Erlo

多线程安全访问共享资源(互斥)

2025-11-03 15:29:01 发布   30 浏览  
页面报错/反馈
收藏 点赞

概念

1.多个执行流进行安全访问的共享资源——临界资源
2.多个执行流中,访问临界资源的代码——临界区--往往是线程代码的很小一部分
3.想让多个线程串行访问共享资源——互斥
4.对一个资源进行访问的时候,要么不做,要么做完——原子性

解决方案:

解决方案:加锁

互斥锁pthread_mutex_t确保同一时间只有一个线程能进入临界区

一、POSIX线程库(pthread)互斥锁(Mutex)接口

函数接口 功能描述 参数与返回值
pthread_mutex_init 初始化互斥锁 - 参数:pthread_mutex_t *mutex(锁对象)、const pthread_mutexattr_t *attr(属性,通常为NULL
- 返回值:成功返回0,失败返回错误码。
pthread_mutex_destroy 销毁互斥锁(释放资源) - 参数:pthread_mutex_t *mutex(已初始化的锁对象)
- 返回值:成功返回0,失败返回错误码。
pthread_mutex_lock 加锁(阻塞式):若锁已被占用,当前线程会阻塞等待 - 参数:pthread_mutex_t *mutex
- 返回值:成功返回0,失败返回错误码(如被信号中断返回EINTR)。
pthread_mutex_trylock 尝试加锁(非阻塞式):若锁已被占用,立即返回失败,不阻塞 - 参数:pthread_mutex_t *mutex
- 返回值:成功返回0,失败返回EBUSY(锁被占用)或其他错误码。
pthread_mutex_unlock 解锁:释放锁,唤醒等待队列中的一个线程 - 参数:pthread_mutex_t *mutex
- 返回值:成功返回0,失败返回错误码(如未加锁时解锁返回EPERM)。

二、C++标准库()基础互斥锁类

类名 功能描述 核心成员函数
std::mutex 基础互斥锁(不可递归,同一线程不能重复加锁) - lock():加锁(阻塞)
- try_lock():尝试加锁(非阻塞,成功返回true
- unlock():解锁
std::recursive_mutex 递归互斥锁:允许同一线程多次加锁(需对应次数的解锁) std::mutex,但支持同一线程重复lock()(次数不超过实现限制)
std::timed_mutex 带超时的互斥锁:支持在指定时间内尝试加锁 增加try_lock_for(std::chrono::duration)try_lock_until(std::chrono::time_point)

如果锁是局部的需要用pthread_mutex_destroyint pthread_mutex_init来创建和销毁,如果是全局或者静态的,则直接用pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;进行初始化

code:

Mutex.hpp:

#pragma once
#include
class Mutex{
public:
    Mutex(const pthread_mutex_t &mtx):mtx_(mtx){
        pthread_mutex_lock(&mtx_);
    }
    ~Mutex(){
        pthread_mutex_unlock(&mtx_);
    }
private:
    pthread_mutex_t mtx_;
};

main:

#include
#include
#include
#include
#include
#include "Mutex.hpp"
int tickets=10000;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
class ThreadData{
public:
    pthread_t m_tid;
    char m_buffer[64];
};
void *getTicket(void *args){
    ThreadData* td=static_cast(args);
    long long getnum=0;
    while(true){
        {
            Mutex m(mutex);
            usleep(1254);
            if(tickets>0){
                std::coutm_buffer tds;
#define NUM 10
    for(int i=1;im_buffer,sizeof(td->m_buffer),"thread[%d]",i);
        int n=pthread_create(&td->m_tid,nullptr,getTicket,(void*)td);
        assert(n==0);
        (void)n;
        tds.push_back(std::move(td));
    }
    for(int i=0;im_tid,(void**)&ret);
        assert(n==0);
        (void)n;
        std::coutm_buffer

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认