【C++】 线程的互斥与同步

同一个进程的线程共享进程内的绝大部分资源,当一段访问这些共享资源的代码块,有可能被多个线程执行时,那么这段代码块就称为临界区
当有多个线程并发的在临界区执行时,程序的执行结果会出现不确定性,这种情况称之为竞态条件

多线程编程中,避免出现竞态条件的一项重要解决方案就是,保证多个线程在临界区是互斥的。所谓的互斥,就是指不能同时有多于一个线程进入临界区。 保证临界区互斥的重要技术,就是互斥锁。 互斥锁的初始化,有两种方式:静态初始化和动态初始化。

使用互斥锁,保证临界区互斥的一般思路是:

1. 为该临界区分配一把互斥锁;
2. 任何想要进入临界区的线程都必须先持有该互斥锁;
3. 持有互斥锁运行于临界区的线程在离开临界区后必须释放该互斥锁;
4. 假设某一临界区正在被一个线程A执行着,这意味着线程A持有该临界区的互斥锁M,如果此时有另一个线程B企图持有互斥锁M进入临界区,那么线程B将会进入阻塞状态。

使用互斥锁最常见的错误就是死锁,而所谓的死锁是指一个线程为了持有一把互斥锁而永远的阻塞了。 造成死锁原因主要有以下两种:

一个线程试图对其已经持有的互斥锁进行再次加锁;
当有需要持有多把锁时,线程间加锁的顺序不同时,也会造成死锁,如下图所示:

3-2.1.2-1

互斥锁的一个主要特点是,谁先拿到锁先就可以优先访问共享资源,因此多个线程访问共享资源的互斥性是得到了保证,但是在某些场合可能还希望确保线程间执行的顺序。

如我们有一个共享内存数据资源M,我们整个程序设计需求是要求线程A在M上做了处理之后,线程B才能做处理。这种需要确保多线程间执行先后顺序的技术,称为线程的同步。

条件变量是线程同步的主要手段。其大致的实现思想就是:

线程B,调用条件变量的接口让自身阻塞;

线程A,在处理完资源后,通过条件变量接口唤醒正在等待该资源的线程B。

条件变量的初始化也有静态初始化和动态初始化两种方式。

猜你喜欢

转载自blog.csdn.net/onlyongwang/article/details/82319450
今日推荐