Linux线程互斥相关函数及其概念

一,进程线程间的互斥相关背景概念

  • 临界资源:多线程执行流共享的资源就叫做临界资源

  • 临界区:每个线程内部,访问临界自娱的代码,就叫做临界区

  • 互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用
  • 原子性(后面讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成

二,互斥量mute​​​​​​​

  • 多个线程并发的操作共享变量,会带来一些问题。
  • 大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个 线程,其他线程无法获得这种变量。
  • 但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,可以通过数据的共享,完成线程之 间的交互。

四,互斥锁常用的函数

pthread_mutex_init函数

作用:初始化一个锁

原型:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t
*restrict attr);
参数:
mutex :要初始化的互斥量
attr :设置所的相关属性,如果设为空则代表使用默认的属性
返回值:如果成功,pthread_mutex_destroy()和pthread_mutex_init()函数将返回零;否则,将返回一个错误编号给indi‐找出错误
pthread_mutex_destroy函数
作用:销毁一个锁
原型:
int pthread_mutex_destroy( pthread_mutex_t *restrict_mutex);
参数: restrict_mutex要销毁的锁
返回值: 如果成功,pthread_mutex_destroy()和pthread_mutex_init()函数将返回零;否则,将返回一个错误编号给indi‐找出错误
pthread_mutex_lock函数
作用:关锁
原型:
int pthread_mutex_lock(pthread_mutex_t *restrict_mutex)
参数:
restrict_mutex:要关的锁
返回值:如果成功,pthread_mutex_lock()和pthread_mutex_unlock()函数将返回零;否则,将返回一个错误编号来指示这个错误。
pthread_mutex_unlock函数
作用:开锁
原型:
int pthread_mutex_unlock(pthread_mutex_t *restrict_mutex)
参数:
restrict_mutex:要开的锁
返回值:如果成功,pthread_mutex_lock()和pthread_mutex_unlock()函数将返回零;否则,将返回一个错误编号来指示这个错误。
以上函数在具体操作中的使用如下:
#include <iostream>
#include <pthread.h>

using namespace std;
int count = 100000;
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

class my_mutex
{
public:

    const char* arr;
    pthread_mutex_t* _mutex;
public:
    my_mutex(const char* arg,pthread_mutex_t* mutex)
    :arr(arg),
    _mutex(mutex)
    {}
    ~my_mutex()
    {
        arr=nullptr;
    }
};

void *fun(void *arg)
{
    my_mutex* a=(my_mutex*)arg;
    while (true)
    {
        pthread_mutex_lock((a->_mutex));
        if (count > 0)
        {
            cout << a->arr << " " << count << "   " << pthread_self() << endl;
            count--;
            pthread_mutex_unlock((a->_mutex));
        }
        else
        {
            pthread_mutex_unlock((a->_mutex));
            break;
        }
    }
}
int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex,nullptr);
    pthread_t thread1; my_mutex mutex1("线程一",&mutex);
    pthread_t thread2; my_mutex mutex2("线程二",&mutex);
    pthread_t thread3; my_mutex mutex3("线程三",&mutex);
    pthread_create(&thread1, nullptr, fun, (void *)&mutex1);
    pthread_create(&thread2, nullptr, fun, (void *)&mutex2);
    pthread_create(&thread3, nullptr, fun, (void *)&mutex3);

    pthread_join(thread1, nullptr);
    pthread_join(thread2, nullptr);
    pthread_join(thread3, nullptr);
    pthread_mutex_destroy(&mutex);

    cout << "从线程全部退出" << endl;

    return 0;
}

最后一条语句打印count为1,代表锁的使用成功

五,可重入VS线程安全

  • 线程安全:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作, 并且没有锁保护的情况下,会出现该问题。
  • 重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们 称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任题,则该函数被称为可重 入函数,否则,是不可重入函数
六,常见的线程不安全的情况
  • 不保护共享变量的函数
  • 函数状态随着被调用,状态发生变化的函数
    返回指向静态变量指针的函数
    调用线程不安全函数的函数
七, 常见的线程安全的情况
  • 每个线程对全局变量或者静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的
  • 类或者接口对于线程来说都是原子操作
    多个线程之间的切换不会导致该接口的执行结果存在二义性
### 死锁四个必要条件
互斥条件:一个资源每次只能被一个执行流使用
请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放
不剥夺条件 : 一个执行流已获得的资源,在末使用完之前,不能强行剥夺
循环等待条件 : 若干执行流之间形成一种头尾相接的循环等待资源的关系
### 避免死锁
​​​​​​​
破坏死锁的四个必要条件
加锁顺序一致
避免锁未释放的场景
资源一次性分配

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值