IO与进程篇 LESSON6 线程互斥与条件变量

目录

线程互斥概念

互斥专业词语

函数接口

初始化互斥锁

添加锁

解开锁

销毁锁

一个简单的使用互斥锁实现互斥程序

条件变量实现线程同步机制

条件变量函数接口

初始化条件变量

等待条件变量的产生

产生条件变量

条件变量销毁

条件变量代码实例


线程互斥概念

在计算机程序中,线程互斥是指多个线程尝试访问共享资源时出现冲突的情况。

例如,当两个线程同时尝试写入同一内存位置时,由于同时进行写入可能会导致数据的不一致性,因此需要确保只有一个线程能够访问该内存位置。

为了避免这种冲突,通常使用互斥锁(mutex)来实现线程互斥。互斥锁是一种同步原语,它可以确保在任何时刻只有一个线程能够访问共享资源。当一个线程需要访问共享资源时,它会尝试获取互斥锁。如果锁已经被另一个线程持有,那么该线程会被阻塞直到锁被释放。当持有锁的线程完成对共享资源的访问后,它会释放互斥锁,允许其他线程继续访问共享资源。

通过使用互斥锁,程序可以确保在任何时刻只有一个线程能够访问共享资源。

互斥专业词语

临界资源: 一次仅允许一个进程所使用的资源

临界区:指的是一个访问共享资源的程序片段

互斥:多个线程在访问临界资源时,同一时间只能一个线程访问

互斥锁:通过互斥锁可以实现互斥机制,主要用来保护临界资源,每个临界资源都由一个互斥锁来保护,线程必须先获得互斥锁才能访问临界资源,访问完资源后释放该锁。如果无法获得锁,线程会阻塞直到获得锁为止。

函数接口

初始化互斥锁

int  pthread_mutex_init(pthread_mutex_t  *mutex, pthread_mutexattr_t *attr)  
功能:初始化互斥锁  
参数:mutex:互斥锁
    attr:  互斥锁属性  //  NULL表示缺省属性
返回值:成功 0
      失败 -1

添加锁

int  pthread_mutex_lock(pthread_mutex_t *mutex)   
功能:申请互斥锁     
参数:mutex:互斥锁
返回值:成功 0
      失败 -1

注意:pthread_mutex_lock是阻塞的。

解开锁

int  pthread_mutex_unlock(pthread_mutex_t *mutex)   
功能:释放互斥锁     
参数:mutex:互斥锁
返回值:成功 0
      失败 -1

销毁锁

int  pthread_mutex_destroy(pthread_mutex_t  *mutex)  
功能:销毁互斥锁     
参数:mutex:互斥锁

一个简单的使用互斥锁实现互斥程序

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int i = 0;
int arr[5] = {1, 2, 3, 4, 5};
pthread_mutex_t lock_t;
void *handly1(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&lock_t);
        puts("1");
        sleep(1);
        puts("2");
        sleep(1);
        puts("3");
        sleep(1);
        pthread_mutex_unlock(&lock_t);
    }
}
void *handly2(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&lock_t);
        puts("子线程1");
        sleep(1);
        puts("子线程2");
        pthread_mutex_unlock(&lock_t);
    }
}

int main(int argc, char const *argv[])
{
    if (pthread_mutex_init(&lock_t, NULL) != 0)
    {
        perror("mutex_init err.");
        return -1;
    }
    pthread_t pid1;
    if (pthread_create(&pid1, NULL, handly1, NULL) != 0)
    {
        perror("create err.");
        return -1;
    }

    pthread_t pid2;
    if (pthread_create(&pid2, NULL, handly2, NULL) != 0)
    {
        perror("create err.");
        return -1;
    }

    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);
    return 0;
}

因为添加了互斥锁当handly1运行的时候,handly2无法运行;可自己运行观测下(建议观测久一点,因为互斥有随机性,不是按照约定来)

条件变量实现线程同步机制

在多线程编程中,条件变量是一种线程间同步的机制,它允许一个线程等待另一个或多个线程满足某个条件后再执行。条件变量通常与锁结合使用,以实现线程间的安全通信和互斥操作。

条件变量函数接口

初始化条件变量

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
功能:初始化条件变量
参数:cond:是一个指向结构pthread_cond_t的指针
    restrict attr:是一个指向结构pthread_condattr_t的指针,一般设为NULL
返回值:成功:0 失败:非0

等待条件变量的产生

int pthread_cond_wait(pthread_cond_t *restrict cond,    pthread_mutex_t *restrict mutex);
功能:等待条件的产生
参数:restrict cond:要等待的条件
     restrict mutex:对应的锁
返回值:成功:0,失败:不为0

注意:等待是阻塞的等待,同时会将锁解开;当等到条件的时候, pthread_cond_wait会结束阻塞同时再次上锁

产生条件变量

int pthread_cond_signal(pthread_cond_t *cond);
功能:产生条件变量
参数:cond:条件变量值
返回值:成功:0,失败:非0

注意:必须先pthread_cond_wait等待后,再触发pthread_cond_signal才会生效,单独的的触发pthread_cond_signal是没用的。

条件变量销毁

int pthread_cond_destroy(pthread_cond_t *cond);
功能:将条件变量销毁
参数:cond:条件变量值
返回值:成功:0, 失败:非0

条件变量代码实例

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int i = 0;
int arr[5] = {1, 2, 3, 4, 5};
pthread_mutex_t lock_t;
pthread_cond_t cond;
void *handly1(void *arg)
{
    while (1)
    {
        sleep(1);
        pthread_mutex_lock(&lock_t);
        pthread_cond_signal(&cond);
        puts("1");
        sleep(1);
        puts("2");
        sleep(1);
        puts("3");
        sleep(1);
        pthread_cond_wait(&cond,&lock_t);//若是阻塞,程序就什么都干不了,一直阻塞
        pthread_mutex_unlock(&lock_t);
    }
}
void *handly2(void *arg)
{
    while (1)
    {
        pthread_mutex_lock(&lock_t);
        pthread_cond_signal(&cond);
        puts("子线程1");
        sleep(1);
        puts("子线程2");
        pthread_cond_wait(&cond,&lock_t);
        pthread_mutex_unlock(&lock_t);
    }
}

int main(int argc, char const *argv[])
{
    if (pthread_mutex_init(&lock_t, NULL) != 0)
    {
        perror("mutex_init err.");
        return -1;
    }
    if(pthread_cond_init(&cond,NULL)!=0){
        perror("cond_init err.");
        return -1;
    }

    pthread_t pid1;
    if (pthread_create(&pid1, NULL, handly1, NULL) != 0)
    {
        perror("create err.");
        return -1;
    }

    pthread_t pid2;
    if (pthread_create(&pid2, NULL, handly2, NULL) != 0)
    {
        perror("create err.");
        return -1;
    }

    pthread_join(pid1, NULL);
    pthread_join(pid2, NULL);
    return 0;
}

上面代码是互斥锁和条件变量让原本无序打印的两个线程,按照想要的结果进行打印。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值