linux系统编程—线程—互斥锁与条件变量

互斥锁概念

引入互斥锁的概念,用来保证共享数据操作的完整性。每个对象都对应于一个可称为互斥锁的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

互斥锁和信号量的区别

1.互斥锁保证了使用资源线程的唯一性和排他性,但是无法限制资源释放后其他线程申请的顺序问题,所以是无序的。而信号量一般就是互斥的(少许情况读取是可以同时申请的),其保证了线程执行的有序性,可以理解为从一到多的进步

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

2.互斥量值只能为0/1,信号量值可以为非负整数。也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问。

3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

条件变量概念

条件变量让进程能够一直睡眠等待直到某种条件满足才开始执行。

如果我们要达到一个条件,就加锁执行后续代码,但如果要一直检测,就需要一直加锁,那就会浪费锁资源,即使用双重锁,还是要不断地做判断。而用了条件变量,只需要一次判断,如果不满足条件,那就阻塞在那。

互斥锁的初始化和销毁函数

#include <pthread.h>
//初始化互斥锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);

pthread_mutex_init和pthread_mutex_destroy参数一和通过pthread_mutex_t创建,参数需要的是一个指针

pthread_mutex_init参数二通常为NULL

返回值:若成功返回0,否则返回错误编号

互斥锁的加锁和解锁函数

#include <pthread.h>
//加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
//解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//
int pthread_mutex_trylock(pthread_mutex_t *mutex);

如果线程不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock就会失败,不能锁住互斥量,而返回EBUSY。

参数通过pthread_mutex_t创建

返回值:若成功返回0,否则返回错误编号

条件变量的销毁和创建函数

#include <pthread.h>
//创建 
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//销毁 
int pthread_cond_destroy(pthread_cond_t cond);

pthread_cond_init参数一: 需初始化的条件变量(由pthread_cond_t 创建)

pthread_cond_init参数二: 设置的条件变量属性

pthread_cond_destroy参数:需销毁的条件变量(由pthread_cond_t 创建)

返回值:若成功返回0,否则返回错误编号

条件变量的等待和唤醒(触发)

#include<pthread.h>

//等待
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
//唤醒(触发)
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

pthread_cond_wait参数一:等待的条件变量(由pthread_cond_t 创建)

pthread_cond_wait参数二::所使用的互斥锁

pthread_cond_signal和pthread_cond_broadcast参数:要唤醒的条件变量(由pthread_cond_t 创建)

返回值:若成功返回0,否则返回错误编号

在调用 pthread_cond_wait 之前,若没有互斥锁的保护,则线程有可能达等待信号发生阶段前收到信号,结果自然是信号成功的被忽略掉,程序阻塞在等待信号中。

互斥锁代码示例

#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex1;

void *func1()
{
    int i;
    pthread_mutex_lock(&mutex1);
    for(i=0;i<5;i++)
    {
        printf("t1 id:%ld\n",(unsigned long)pthread_self());
    }
    printf("========================\n");
    pthread_mutex_unlock(&mutex1);
}

void *func2()
{
    pthread_mutex_lock(&mutex1);
    printf("t2 id:%ld\n",(unsigned long)pthread_self());
    pthread_mutex_unlock(&mutex1);
}
void *func3()
{
    pthread_mutex_lock(&mutex1);
    printf("t3 id:%ld\n",(unsigned long)pthread_self());
    pthread_mutex_unlock(&mutex1);
}

int main()
{
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;

    pthread_mutex_init(&mutex1,NULL);
    if( pthread_create(&t1, NULL, func1,NULL) != 0)
    {
        printf("Failed to create t1\n");
    }
    if( pthread_create(&t2, NULL, func2,NULL) != 0)
    {
        printf("Failed to create t2\n");
    }
    if( pthread_create(&t3, NULL, func3,NULL) != 0)
    {
        printf("Failed to create t3\n");
    }

    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    pthread_join(t3,NULL);

    pthread_mutex_destroy(&mutex1);

    return 0;
}

编译运行看到五次运行都是t1先运行之后放锁,t2和t3才运行。

 用system函数调用100次

#include <stdio.h>
#include <stdlib.h>


int main()
{
    int i;
    for(i=0;i<100;i++)
    {
        system("./a.out");
    }

    return 0;
}

编译运行,将运行结果存放在file.txt中

gcc system.c -o system

./system > file.txt

 条件变量代码示例

#include <stdio.h>
#include <pthread.h>

int g_data = 0;

pthread_mutex_t mutex;
pthread_cond_t cond;

void *func1()
{
    printf("t1:%ld thread is create\n",(unsigned long)pthread_self());

    static int cnt = 0;

    while(1){

        pthread_cond_wait(&cond,&mutex);//等待
        printf("t1 run================================\n");

        printf("t1: g_data = %d\n",g_data);
        g_data = 0;
        sleep(1);
        if(cnt++ == 5){
            exit(1);
        }
    }
}

void *func2()
{
    printf("t2:%ld thread is create\n",(unsigned long)pthread_self());

    while(1){

        printf("t2: g_data = %d\n",g_data);
        pthread_mutex_lock(&mutex);//拿锁
        g_data++;//printf在前 ++在后 当输出t2gdate=2时,条件就已经触发
        if(g_data == 3){
            pthread_cond_signal(&cond);//等于3时触发条件
        }
        pthread_mutex_unlock(&mutex);//放锁
        sleep(1);
    }
}
int main()
{
    pthread_t t1;
    pthread_t t2;
    //初始化
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    //创建
    pthread_create(&t1, NULL, func1,NULL);
    pthread_create(&t2, NULL, func2,NULL);
    //等待
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    //销毁
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

编译运行

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值