线程的互斥机制——实现线程之间的有序访问共享资源

线程互斥锁

线程互斥锁也是 信号量 ,只不过线程互斥锁,存在于进程地址空间,用于线程间同步和互斥操作,线程互斥锁它的效率相对信号量来说要高。
线程互斥锁:使用 pthread_mutex_t 的类型来描述一个锁。

这里用到POSIX(可移植操作系统接口)

安装线程 POSIX 帮助手册: sudo apt-get install manpages-posix-dev // 安装posix 帮助手册

初始化线程互斥锁

NAME
pthread_mutex_init — destroy and initialize a mutex
SYNOPSIS
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const
pthread_mutexattr_t *restrict attr);
/*
@描述:
线程互斥锁的PV 操作
P 操作(上锁操作)
初始一个线程互斥锁
@mutex:
需要初始化的线程互斥锁地址
pthread_mutex_t mutex; // 创建了一个互斥锁
&mutex ---> 互斥锁地址
@attr:
线程互斥锁的属性,一般为NULL,采用默认属性
如:
线程的互斥锁默认设置 1 unlock
@return:
成功返回0,失败返回-1
*/

线程互斥锁的PV 操作

P 操作(上锁操作)

int pthread_mutex_lock(pthread_mutex_t *mutex);
/*
作用:
死等上锁,如果该锁没有被释放,则会一直阻塞在此函数,等待该锁被释放。
@mutex:
需要上锁的互斥锁指针
@return:
成功返回0,表示获取到了该互斥锁
返回-1,表示获取出错,没有获取到互斥锁
*/
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/*
作用:
尝试上锁,尝试性上锁,如果该锁没被释放,那么立即返回执行后面的代码。
@mutex:
需要上锁的互斥锁指针
@return:
成功返回0,表示获取到了该互斥锁
其他值,表示没有获取到互斥锁
*/
int pthread_mutex_timedlock(pthread_mutex_t *mutex,struct timespec
*abs_timeout);
/*
作用:
限时上锁,如果该锁没有被释放,则会一直阻塞在此函数中一段实际,等待该锁被释放。如果时间
过了还没有被释放,那么果断放弃执行后面的代码。
@mutex:
需要上锁的互斥锁指针
@abs_timeout:
绝对时间(超时时间),上锁的时间范围。
@return:
成功返回0,表示获取到了该互斥锁

V 操作(解锁操作)

int pthread_mutex_unlock(pthread_mutex_t *mutex);
/*
作用:
解锁线程互斥锁
@mutex:
需要解锁的线程互斥锁指针
*/

线程互斥锁的销毁操作

int pthread_mutex_destroy(pthread_mutex_t *mutex);
/*
作用:
销毁一个线程互斥锁
@mutex:
需要销毁的线程互斥锁指针
@return:
成功返回0,失败返回-1
*/

线程条件变量

线程条件变量:在多线程程序设计中,可以用 条件变量 为表示一个特定的条件或者是事件
pthread_cond_t :来描述一个条件变量(类型)
至于条件变量,到底是一个什么事件或者说表示一个什么条件?完全由程序猿去解释这个条件变量所代表的含义。
在条件变量上的三种操作:

初始化
等待一个条件变量(等待该条件变量所表示的事件)
唤醒一个线程/触发条件变量(唤醒了正在等待该事件的线程)

举个栗子

int data = 0;
main : 主线程:生产者:包工头
data = 1;
t1:子线程:消费者:牛马
when data == 1;
干活
data = 0;

线程条件变量API

初始化/销毁条件变量

NAME
pthread_cond_destroy, pthread_cond_init — destroy and initialize
condition variables
SYNOPSIS
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
等待一个条件变量
/*
@描述:
销毁一个条件变量
@cond:
需要销毁条件变量指针
*/
int pthread_cond_init(pthread_cond_t *restrict cond,const
pthread_condattr_t *restrict attr);
/*
@描述:
初始化一个条件变量
@cond:
需要初始化的条件变量的指针
@attr:
初始化的条件变量的属性,一般为NULL,采用默认设置
@return:
成功返回0,失败返回其他值
*/

等待一个条件变量

NAME
pthread_cond_timedwait, pthread_cond_wait — wait on a condition
SYNOPSIS
#include <pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t
*restrict mutex,
const struct timespec *restrict abstime);
/*
@描述:
限时等待条件变量
@cond:
需要等待的那个条件变量指针
@mutex:
线程互斥锁:为了保护cond所表示的那个事件/共享资源的。
条件变量实际也是一个共享资源。
@abstime:
绝对时间,需要被唤醒的绝对时间
*/
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t
*restrict mutex);
/*
唤醒线程/触发条件变量
@描述:
等待那个条件变量
@cond:
需要等待的那个条件变量指针
@mutex:
线程互斥锁:为了保护cond所表示的那个事件/共享资源的。
条件变量实际也是一个共享资源。
pthread_cond_wait()
{
mutex:locked 上锁
... 准备工作
mutex:unlock 解锁
让出CPU 等待
...
when 当条件产生的时候,其他的线程唤醒我的时候
mutex:locked 上锁
}
@return:
成功返回0,被其他线程唤醒
失败返回其他值
*/

唤醒线程/触发条件变量

NAME
pthread_cond_broadcast, pthread_cond_signal — broadcast or signal a
condition
SYNOPSIS
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond);
/*
@描述:
唤醒所有正在等待的线程
@cond:
那个条件变量
@return:
成功返回0,失败返回其他值
*/
int pthread_cond_signal(pthread_cond_t *cond);
/*
@描述:
只唤醒一个线程在等待的线程。
@cond:
那个条件变量
@return:
成功返回0,失败返回其他值
*/

代码示例(可运行)

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
using std::vector;

// 线程互斥锁
pthread_mutex_t mutex;

// 条件变量
pthread_cond_t cond;

// 公共资源
FILE *file=NULL;
std::string str;

// 消费者,这是个线程函数。
void *NiuMa(void *data)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        // 等待条件变量:任务
        pthread_cond_wait(&cond,&mutex); // 休眠,让出了CPU。这里有个机制,不会让子线程一直占据锁。
        
        if(str == "退出")
        {
           pthread_mutex_unlock(&mutex);     

            pthread_exit(NULL);
        }

        std::cout << fwrite(str.c_str(),str.size(),1,file) << std::endl;

        std::cout << pthread_self() << "线程:成功写入内容:<" << str << "> "<< std::endl;
        
        pthread_mutex_unlock(&mutex);


    }

}

// 主线程:生产者
int main()
{
    // 初始化
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);

    // 打开文件
    file = fopen("./1.txt","w+");

    vector<pthread_t> tids(10);

    // 创建10个线程
    for(int i = 0;i < 10;i++)
    {
        pthread_create(&tids[i],NULL,NiuMa,NULL);
    }

    // 通过输入来发布任务
    while(1)
    {

        sleep(4);
        pthread_mutex_lock(&mutex);

        std::cout << "请输入内容:" ;
        std::cin >> str;

        pthread_mutex_unlock(&mutex);

        if(str == "退出")
        {
            pthread_cond_broadcast(&cond);
            break;
        }

        //唤醒线程
        pthread_cond_signal(&cond);
        break;
    }

    for(int i = 0;i < 10;i++)
    {
        pthread_join(tids[i],NULL);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    fclose(file);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值