一、锁的基本思想
- 通过加锁来保证临界区的原子性
lock_t mutex;
...
lock(&mutex);
// 获取锁,如果已被占用, 则等待,直到获得锁为止
balance = balance + 1;
unlock(&mutex);
// 释放锁
- 如何评价锁的实现
- 有效性:只有一个线程能拿到锁
- 公平性:所有线程都有机会拿到锁
- 不会出现饿死情况
- 性能:时间开销小
锁的实现一般要使用某种特 殊硬件指令,但也可以不用
- 锁的实现:用中断屏蔽指令(例如x86的CLI)
- 只适用于单处理器系统
- 需要在内核态运行(开关中断是特权指令)
- 需要运行所有线程执行特权操作
- 影响对中断的及时响应
void lock() {
DisableInterrupts();
}
void unlock() {
EnableInterrupts();
}
二、自旋锁
- 通过忙等待(Busy Waiting)的方式不断检查锁的状态
- 通过循环(自旋)实现
typedef struct __lock_t {
int flag;
} lock_t;
void init(lock_t *mutex) {
// 0 → lock is available, 1 → held
mutex->flag = 0;
}
void lock(lock_t *mutex) {
while (mutex->flag == 1) // TEST the flag
; // spin-wait (do nothing)
mutex->flag = 1; // now SET it !
}
void unlock(lock_t *mutex) {
mutex->flag = 0;
}
typedef struct __lock_t {
int flag;
} lock_t;
void init(lock_t *mutex) {
// 0 → lock is available, 1 → held
mutex->flag = 0;
}
void lock(lock_t *mutex) {
L0:
if (mutex->flag == 1) // TEST the flag
goto L0; // spin-wait (do nothing)
mutex->flag = 1; // now SET it !
}
void unlock(lock_t *mutex) {
mutex->flag = 0;
}
这个锁有问题吗?
缺乏原子性:对 mutex->flag 的检查和设置不是原子操作。在多线程环境中,两个线程可能同时读取 flag 的值并都认为锁是可用的,从而导致数据竞争和不一致的状态。

说些什么吧!