目录

1.常见锁概念:

1.1死锁

1.2死锁的四个必要条件

1.3避免死锁

2.Linux线程同步

2.1条件变量

2.2同步概念与竟态条件

2.3条件变量函数

2.4条件变量使用规范


1.常见锁概念:

1.1死锁

  • 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占,永不会释放的资源而处于的一种永久等待状态

1.2死锁的四个必要条件

  • 互斥条件:一个资源每次只能被一个执行流使用(前提)
  • 请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放(原则)
  • 不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺(原则)
  • 循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系(重要条件)

1.3避免死锁

  • 破坏死锁的四个必要条件
  • 加锁顺序一致
  • 避免锁未释放的场景
  • 资源一次性分配

2.Linux线程同步

2.1条件变量

  • 当一个线程互斥地访问某个变量时,它可能发现在其他线程改变状态之间,它什么也做不了
  • 例如一个线程访问队列时,发现队列为空,它只能等待,只到其他线程将一个节点添加到队列中。这种情况就需要用到条件变量

2.2同步概念与竟态条件

  • 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步
  • 竟态条件:因为时序问题,而导致程序异常,我们称之为竟态条件。

2.3条件变量函数

初始化:

参数:

        cond:要初始化的条件变量

        attr:NULL

销毁:

等待条件满足:

参数:
        cond:要在这个条件变量上等待

        mutex:互斥量,后面详细讲

唤醒等待:

简单案例:

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

pthread_cond_t cond;
pthread_mutex_t mutex;

void *r1(void *arg)
{
    while(1)
    {
        pthread_cond_wait(&cond,&mutex);
        printf("活动\n");
    }
}

void *r2(void *arg)
{
    while(1)
    {
        pthread_cond_signal(&cond);
        sleep(1);
    }
}

int main()
{
    pthread_t t1,t2;

    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&mutex,NULL);

    pthread_create(&t1,NULL,r1,NULL);
    pthread_create(&t2,NULL,r2,NULL);

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

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

为什么pthread_cond_wait需要互斥量?

  • 条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程
  • 条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据

  • 按照上面的说法,我们设计出如下的代码:先上锁,发现条件不满足,解锁,然后等待在条件变量上不就性了,如下代码:
//错误的设计
pthread_mutex_lock(&mutex);
while(condition_is_false)
{
    pthread_mutex_unlock(&mutex);
    //解锁之后,等待之间,条件可能已经满足,信号已经发出,但是该信号可能被错过
    pthread_cond_wait(&cond);
    pthread_mutex_lock(&mutex);
}
pthread_mutex_unlock(&mutex);
  • 由于解锁和等待不是原子操作。调用解锁之后,pthread_cond_wait之前,如果已经有其他线程获取到互斥量,摒弃条件满足,发送了信号,那么pthread_cond_wait将错过这个信号,可能会导致线程永远阻塞在这个pthread_cond_wait。所以解锁和等待必须必须是一个原子·操作
  • 进入该函数后,会去看条件量等于0不?等于,就把互斥量变成1,直到cond_wait返回,把条件量改成1,把互斥量恢复成原样。

2.4条件变量使用规范

等待条件代码:

pthread_mutex_lock(&mutex);
while(条件为假)
    pthread_cond_wait(cond,mutex);
修改条件
pthread_mutex_unlock(&mutex);

给条件发送信号代码:

pthread_mutex_lock(&mutex);
设置条件为真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐