线程学习--pthread--锁链及条件变量

本文介绍了如何使用pthread库中的条件变量(pthread_cond_wait)在多线程环境中实现线程间的同步,以按顺序打印字母'a'到'd'。通过对比分析了两种方法,一种是锁链方式,另一种是正确使用条件变量,强调了在使用pthread_cond_wait时应先加锁并检查条件,避免死锁。示例代码展示了条件变量在多线程同步中的应用。
摘要由CSDN通过智能技术生成

pthread_cond_wait函数的使用,一般跟lock一起用

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
  1. 等待条件变量满足;
  2. 把获得的锁释放掉;(注意:1,2两步是一个原子操作) 当然如果条件满足了,那么就不需要释放锁。所以释放锁这一步和等待条件满足一定是一起执行(指原子操作)。--很重要。
  3. pthread_cond_wait()被唤醒时,它解除阻塞,并且尝试获取锁(不一定拿到锁)。因此,一般在使用的时候都是在一个循环里使用pthread_cond_wait()函数,因为它在返回的时候不一定能拿到锁(这可能会发生饿死情形,当然这取决于操作系统的调度策略)。

首先加锁pthread_mutex_lock(),等待条件变量的到来,通常在一个while循环中使用,条件变量唤醒,不满足条件,解锁继续等待下一次条件变量的到来。

需求创建4个线程,每一个线程打印一个字符,按顺序打印abcd

第一版--锁链,不建议使用这种方法,可能会产生未定义行为

原理:创建四个线程,四把锁,第一线程解下一个线程的锁(不同的线程解同一把会产生未定义行为)

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

#define NUM 4
pthread_mutex_t mutex[NUM];

int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}

void *handler(void *p)
{
    int i = *(int*)p;
    while(1)
    {
        pthread_mutex_lock(mutex+i);
        printf("%d",i+1);
        pthread_mutex_unlock(mutex+next(i));
    }

    pthread_exit(p);
}

int main()
{
    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    for(; i < NUM; i++)
    {
        int *num = malloc(sizeof(int));
        *num = i;
        //mutex[i] = PTHREAD_MUTEX_INITIALIZER;//PTHREAD_MUTEX_INITIALIZER
        pthread_mutex_init(mutex+i, NULL);
        pthread_mutex_lock(mutex+i);
        if(pthread_create(tid+i, NULL, handler, (void*)num))
        {
            perror("pthread_create()");
            exit(-1);
        }
    }
    pthread_mutex_unlock(mutex);

    alarm(1);

    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    
    exit(0);
}

第二种方法:使用条件变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int num = 0;
static int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}
static void *handler(void *p)
{
    int i = *(int*)p;
    while(1)
    {
        pthread_mutex_lock(&mutex);//注释掉的锁挪到这里就可以了。
        while(num != i)
            pthread_cond_wait(&cond, &mutex);
        //之前把锁放在这里,产生了死锁,一直搞不懂,
        //1.应先加锁,再查看num值
        //2.pthread_cond_wait是等待条件变量的到来,如果到来,拿到锁,然后释放锁。
        //pthread_mutex_lock(&mutex);
        printf("%d", num);
        num = next(num);
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(p);
}
int main()
{
    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    pthread_mutex_init(&mutex, NULL);
    pthread_mutex_lock(&mutex);
    for(; i < NUM; i++)
    {
        int *num = malloc(sizeof(int));
        *num = i;
        if(pthread_create(tid+i, NULL, handler, (void*)num))
        {
            perror("pthread_create()");
            exit(-1);
        }
    }
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
    alarm(1);
    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    exit(0);
}

更简洁条件变量版:不在主线程中加锁

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

#define NUM 4
pthread_mutex_t mutex;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int num = 0;

static int next(int i)
{
    if(i == 3)
        return 0;
    return i+1;
}

static void *handler(void *p)
{
    int i = (int)p;
    while(1)
    {
        pthread_mutex_lock(&mutex);
        while(num != i)
            pthread_cond_wait(&cond, &mutex);
        num = next(num);
        printf("%d", num);
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(p);
}

int main()
{

    int i = 0;
    pthread_t tid[NUM];
    void *ptr = NULL;
    
    pthread_mutex_init(&mutex, NULL);
    for(; i < NUM; i++)
    {
        if(pthread_create(tid+i, NULL, handler, (void*)i))
        {
            perror("pthread_create()");

            exit(-1);
        }
    }

    alarm(2);

    for(i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], ptr);
        free(ptr);
    }
    
    exit(0);
}

--李慧琴老师课程笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值