大部分答案: 这是一个ps文件
这是一个在线转换工具:
34 ~ 41: 见参考答案
42.
因为只有一个write重叠,从后往前读。
case 1: b2 == b1,write已经更新完了;返回b2。
case 2: b2 == b1,write正在更新b0;返回b2。这时write可能已经更新了b[2*N + i]的值,但是原来的值已经记录在b2中,而且是上一次更新的值。
case 2: b2 != b1,write正在更新b1;返回b0。因为只有一个write重叠,所以更新过的b0已经是一个有效值,而且read返回前不会改变。
case 4: b2 != b1,write正在更新b2;返回b0。
从b2到b0读的关键在于,在整个读的过程中只会读到(b2, b1, b0中的)最多一个正在被改变的值。
所以不能从b0往b2读。假如判断是 return (b0 == b1)? b0: b2; 则可能读b2值的时候write正在更新而且没有完成,会返回一个不安全的值。
1 class AcmeRegister implements Register{
2 // N is the total number of threads
3 // Atomic multi-reader single-writer registers
4 private BoolRegister[] b = new BoolMRSWRegister[3 * N];
5 public void write(int x) {
6 boolean[] v = intToBooleanArray(x);
7 // copy v[i] to b[i] in ascending order of i
8 for (int i = 0; i < N; i++)
9 b[i].write(v[i]);
10 // copy v[i] to b[N+i] in ascending order of i
11 for (int i = 0; i < N; i++)
12 b[N+i].write(v[i]);
13 // copy v[i] to b[2N+i] in ascending order of i
14 for (int i = 0; i < N; i++)
15 b[(2*N)+i].write(v[i]);
16 }
17 public int read() {
18 int b2 = booleanArrayToInt(b[2*N], N); //psudo codes
19 int b1 = booleanArrayToInt(b[N], N);
20 int b0 = booleanArrayToInt(b[0], N);
21
22 return (b2 == b1)? b2: b0;
23 }
24 }
43. True
44.
Obstruction-Free 实现:
根据题中定理4.5.3, read()中的c0 >= cl; c1 <= cl; 因为 (c0 == c1) ==> (c0 <= cl && c0 >= cl) == > c0 == cl, 即这是一个规则的实现。根据Note:
If a read of c obtains traces of version cj, j >= 0, then:
The beginning of the read preceded the end of write c(j + 1).
The end of read followed the beginning of the write of cj;
所以如果A不可能读到未来的值,也不会读到过期的值;如果有A.read -> C.read。C只能读到c(j+m)(m>=0)。所以这是一个swmr的原子实现。
class Counter
{
private boolean c[2][M];
private int convert(boolean[] c)
{
//convert c1c2...cm into counter;
return 0;
}
private boolean[] convert(int v)
{
//convert counter value into c array
return boolean[2];
}
public void update(int v)
{
boolean[] cv = convert(v);
for(int i = 0; i < M; i ++)
{
c[0][i] = cv[i];
}
for(int i = M - 1; i >= 0; i --)
{
c[1][i] = cv[i];
}
return;
}
public int scan()
{
boolean b[2][M];
do
{
for(int i = M - 1; i >=0; i --)
{
b[0][i] = c[0][i];
}
for(int i = 0; i < M; i ++)
{
b[1][i] = c[1][i];
}
}while(!Arrays.equals(b[0],b[1]);
return convert(b[0]);
}
}
Wait-Free 实现
在obstruction-free的证明的基础上。
根据section 4.3中的证明,如果A观察到B udpate了2次,则可以用B的scan作为A scan的结果。因为counter值一直增加,所以如果B保存的值 > A collect一次的值,则B有update,因为根据这个实现,B只有update时才会更新它保存的scan值。
import java.util.*;
public abstract class Counter
{
public static final int SIZE = 8;
public static final int N = 8;
public ThreadLocal<Integer> ThreadId;
private int[] c1 = new int[SIZE];
private int[] c2 = new int[SIZE];
private int[] cValueTable = new int[N];
public Counter()
{
}
private int[] convert(int value)
{
return new int[SIZE];
}
private int convert(int[] cValue)
{
return 0;
}
public int scan()
{
int[] scanC1 = new int[SIZE];
int[] scanC2 = new int[SIZE];
boolean[] moved = new boolean[N];
while(true)
{
for(int i = 0; i < c1.length; i ++)
{
scanC1[i] = c1[i];
}
for(int i = c2.length; i >= 0; i --)
{
scanC2[i] = c2[i];
}
int value = convert(scanC1);
if(Arrays.equals(scanC1, scanC2))
{
return value;
}else
{
for(int i = 0; i < N; i ++)
{
if(cValueTable[i] > value && moved[i])
{
return cValueTable[i];
}else
{
moved[i] = true;
}
}
}
}
}
public void update(int value)
{
int me = ThreadId.get().intValue();
int[] cv = convert(value);
for(int i = c1.length; i >=0; i --)
{
c1[i] = cv[i];
}
for(int i = 0; i < c2.length; i ++)
{
c2[i] = cv[i];
}
cValueTable[me] = value;
}
}
45.
(1). 因为有W(C2(k)) --> W(C1(k)) --> R(C1(k)) --> R(C2(k)) ==> 即对任意k,读过c1再读c2,得到的c2版本号一定 >= c1的版本号。所以有 l1 < k2。
(2). 令 c(k, l) = c(i1)c(i2)...c(im)。根据4.5.1,有i1 <= i2 <= ... <= im <= l;根据4.5.2有 c(i1)c(i2)...c(im) <= cl。
46. 见参考答案