什么是临界资源和临界区?并举例说明?
临界资源与临界区的定义
定义解释
临界资源是指多个线程或进程可以共享的资源,这些资源在同一时刻只能由一个线程或进程访问[^1]。如果多个线程试图同时访问该资源,则可能导致数据不一致或其他错误行为。
临界区则是指每个线程内部用于访问临界资源的那一部分代码[^4]。换句话说,临界区是程序中涉及对共享资源操作的一段代码片段,这段代码必须确保同一时间只有一个线程能够执行。
为了防止多个线程同时进入各自的临界区并引发冲突,通常会采用同步机制来保护临界区,比如使用互斥锁(Mutex)、信号量等工具[^2]。
示例说明
以下是几个常见的临界资源和临界区的例子:
示例一:银行账户余额更新
假设有一个简单的银行账户类 BankAccount
和两个线程分别尝试向同一个账户存款和取款。此时,账户余额就是一个典型的临界资源,因为两个线程可能会同时修改这个变量。
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
temp_balance = self.balance # 访问临界资源
temp_balance += amount # 修改临界资源
self.balance = temp_balance # 更新临界资源
def withdraw(self, amount):
temp_balance = self.balance # 访问临界资源
if temp_balance >= amount: # 条件判断
temp_balance -= amount # 修改临界资源
self.balance = temp_balance # 更新临界资源
在这个例子中,deposit
方法和 withdraw
方法都包含了对 balance
的读写操作,因此它们的操作范围构成了临界区。如果没有适当的同步措施,当两个线程交替调用这两个方法时,就可能出现竞态条件(Race Condition),即最终结果依赖于线程调度顺序[^3]。
示例二:计数器增加
另一个常见场景是对全局计数器进行增减操作。例如,有多个生产者线程往队列里添加项目,并通过计数器记录当前项目的总数;与此同时还有消费者线程从中取出项目并将计数器减少相应的数量。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx; // 创建互斥锁对象
int counter = 0;
void increment_counter() {
std::lock_guard<std::mutex> lock(mtx); // 加锁
++counter;
}
void decrement_counter() {
std::lock_guard<std::mutex> lock(mtx); // 加锁
--counter;
}
这里同样存在潜在的竞争情况——假如没有加锁保护的话,不同线程之间对于 counter++
或 counter--
这样的复合表达式的解析过程就会被打断,从而破坏一致性约束。
同步机制的重要性
为了避免上述提到的数据竞争现象发生,在实际开发过程中往往需要借助操作系统提供的各种同步原语来进行协调管理。最常用的方式之一就是利用 互斥锁 (Mutex) 实现基本的排他性控制功能。除此之外还可以考虑更高级别的解决方案如条件变量、屏障或者读者-写者锁等等具体视应用场景而定。
相关推荐















