正确同步的程序是否仍允许数据竞争?(第一部分)

时间:2012-08-17 13:26:06

标签: java multithreading memory-model

JLS有两个结论:

  • C1:如果某个程序没有数据争用,那么程序的所有执行都会显示为顺序一致:data-race-free => sequentially consistent
  • C2:如果程序正确同步,那么程序的所有执行都会显示为顺序一致:correctly synchronized => sequentially consistent

如果C1的反面是真的,那么我们可以得出结论:

  • C3:如果程序正确同步,那么它就没有数据竞争:correctly synchronized => data-race-free

但不幸的是,JLS中没有这样的陈述,所以我得出了第四个结论:

  • C4:程序可以正确同步并具有数据竞争。

但我对这种方法并不满意,并希望得到一个证据,证明这个结论是真的(或错误的),即使是以非正式的方式或以样本的方式。

首先,我认为显示包含数据竞争的多线程程序的顺序一致执行的代码段有助于理解和解决此问题。

经过认真考虑,我仍然找不到合适的样品。那么请你给我这样的代码段吗?

3 个答案:

答案 0 :(得分:5)

一个很好的例子可能是String的哈希码:

private int hash; // Default to 0

public int hashCode() {
    int h = hash;
    if (h == 0 && count > 0) {
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}

这里有一个数据竞争,因为哈希可以由不同的线程写入和读取,并且之前没有发生关系(没有同步)。

然而,程序是顺序一致的,因为线程不可能看到不是字符串的实际哈希码的哈希码(当线程执行哈希码方法时,它可以看到0并重新计算值,这是确定性的,或者它看到一个有效的值)。这是有效的,因为int write是原子的。

修改

这个(几乎)相同的代码被破坏并且可以返回0的哈希码:

public int hashCode() {
    if (hash == 0 && count > 0) { //(1)
        int h = hash;
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return hash; //(2)
}

因为(1)和(2)可以重新排序:(1)可以读取非空值而(2)读取0.这在第一个例子中不会发生,因为计算是在局部变量上进行的返回值也是局部变量,根据定义,它是线程安全的。

编辑2

关于你的命题C4,I don't think it is possible

  

当且仅当所有顺序一致的执行都没有数据争用时,程序才能正确同步。

     

如果程序正确同步,则程序的所有执行都将显示为顺序一致(第17.4.3节)。

因此,如果程序正确同步:

  • 所有执行都按顺序显示。
  • 所有顺序一致的执行都没有数据竞争

因此我们可以得出结论,所有执行都没有数据竞争,因此该程序没有数据竞争。

答案 1 :(得分:1)

竞赛条件意味着让你的程序输出取决于谁首先获得特定点。例如,如果您有2个线程:T1和T2,如果您的程序输出为X,如果T1首先在程序中指向P,并且如果T2首先到达P点,则程序的输出为Y,那么您就有竞争条件。

在伪代码中:

 Global variable i initialized to 6;
 Thread 1: 
       aquire(lock l)
             increment global variable i, i.e. i++;


 Thread 2: 
       aquire(lock l)
             double the value of global var i, i.e.: i*=2;

如果T1获取锁定第一个和T2秒,则i的值将为14 如果T2获取锁定l次,则T1的值为13

答案 2 :(得分:0)

http://rsim.cs.illinois.edu/Pubs/popl05.pdf

证据似乎是这样的:

假设执行正确同步的程序包含数据争用,我们可以找到包含数据争用的顺序执行,违反了“正确同步程序”的定义[C1]

因此,执行不得包含数据竞争。 [C3]从那里,可以证明执行顺序一致。 [C2]

所以C3是真的,它用来证明C2。