转载自http://blog.csdn.net/ganggexiongqi/article/details/6780148
REF: 多处理器编程的艺术(The Art of Multiprocessor Programming)
说明:我自己的理解为红色(不保证正确),参考书上的为黑色。
最后修改时间: 09-16-2011
2.1 时间
- 线程是个状态机,其状态的转换称为事件。
- 事件是瞬间发生的,我们假设不同的事件在不同的时间点发生。
- 事件间隔有重叠时,称为 并发的。
2.2 临界区
- 某个时刻仅能够被一个线程执行的代码,称为临界区。
- 上面的特性,称为 互斥。
-
+ 互斥:不同线程的临界区之间没有重叠。
+ 无死锁:如果一个线程正在尝试获得一个锁,那个总会成功的获得这个锁。
+ 无饥饿:每个试图获得锁的线程最终都能成功。//无饥饿意味着无死锁。
//无饥饿特性不保证线程在进入临界区以前需要等待多长时间。
- 即使程序所使用的每个锁都满足无死锁特性,该程序也可能死锁。
2.3 双线程解决方案
2.3.1 LockOne算法
2.3.2 LockTwo算法
2.3.3 Peterson锁
Peterson锁算法://双线程互斥算法
class Peterson implements Lock {
// thread-local index, 0 or 1
private volatile boolean[] flag = new boolean[2];
private volatile int victim;
public void lock() {
int me = ThreadID.get();
int he = 1 - me;
flag[me] = true; // I’m interested
victim = me; // you go first
while (flag[he] && victim == me) {}; // wait
}
public void unlock() {
int me = ThreadID.get();
flag[me] = false; // I’m not interested
}
}
- Peterson锁是满足互斥特性,是无饥饿,无死锁的。
2.4 过滤锁
算法代码:
class Filter implements Lock {
int[] level;
int[] victim;
public Filter(int n) {
level = new int[n];
victim = new int[n]; // use 1..n-1
for (int i = 0; i < n; i++) {
level[i] = 0; //[1]
}
}
public void lock() {
int me = ThreadID.get();
for (int i = 1; i < n; i++) { //attempt level 1 //[2]
level[me] = i;
victim[i] = me;
// spin while conflicts exist
while ((∃k != me) (level[k] >= i && victim[i] == me)) {}; //[3]
}
}
public void unlock() {
int me = ThreadID.get();
level[me] = 0;
}
}
说明: - n 元整数组level [], level[A]的值表示线程A正在尝试进入的层。
- 每个层都有一个victim[l] 域, 用来选出线程,“留守”本层。
下面是我对代码的通俗的解释:
[1]: 默认所有线程都处于0层 并尝试进入第一层。
[2]: i 表示本次循环,本线程想要进入的层的层号。
[3]: (∃k != me) (level[k] >= i)表示,"me线程“所在层的上一层有线程存在。
如果“victim[i] == me“满足,表示“没有新的线程进入本层”。
对算法的我的理解://!!!假设先调用lock的线程,先进入临界区
第一个进入lock的线程,会畅通无阻的进入下一层,直到进入临界区。
假设第一个进入lock的线程现在处于第X层,此时有第二个线程调用了lock.
那么第二个线程进入第1层。如果没有第三个线程调用lock,那么第二个线程
将会被选择“留守”在第一层。如果有第三个线程调用了lock,那么第二个线程
就可以进入第二层 了。而第三个线程会“留守”。
所有层都满足的特性:
- 至少会有一个尝试进入层L的线程会成功。
- 如果有一个以上的线程要进入层L,则至少有一个线程会被阻塞在L-1层。
引理2.4.1:对于0到n-1中的整数j,层j上最多有n-j个线程。
推论2.4.1: 过滤锁算法满足互斥特性。
引理2.4.2: 过滤锁算法是无饥饿的。
推论2.4.2: 过滤锁算法是无死锁的。