并发设置范围

时间:2016-03-16 20:54:33

标签: java concurrency

我对Concurrency很陌生,但此刻得到了这个要点;我有一个 NOT Thread Safe 的程序,因此可能会破坏类的主要下限小于等于上限的不变量。 我想出了一个主要的方法,希望它在真实时打印出来,但是无法理解为什么它不会。

public class Conc implements Runnable {

    // Invariant: lower <= upper
    private final AtomicInteger lower = new AtomicInteger(0);
    private final AtomicInteger upper = new AtomicInteger(0);

    public void setLower(int l) {
        if (l <= upper.get())
            lower.set(l);
    }

    public void setUpper(int u) {
        if (u >= lower.get())
            upper.set(u);
    }

    public boolean isInRange(int i) {
        return (i >= lower.get() && i <= upper.get());
    }

    public boolean invariantSatisfied() {
        return (lower.get() <= upper.get());
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new Conc());
        Thread t2 = new Thread(new Conc());
        Thread t3 = new Thread(new Conc());

        t1.start();
        t2.start();
        t3.start();
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            setUpper(i - 10000);
            setLower(i + 800000);
            if (invariantSatisfied() == false) {
                System.out.println("False");
            }
            System.out.println();
        }
    }
}

2 个答案:

答案 0 :(得分:1)

此程序存在一些导致意外结果的问题。

首先指出的是代码实际上是线程安全的。 这是因为每个Object都有它自己引用的字段集,每个线程都有自己的对象。

这可以通过几种方式解决

你可以在每个线程中使用相同的对象

  Conc target = new Conc ();
  Thread t1 = new Thread(target);
  Thread t2 = new Thread(target);
  Thread t3 = new Thread(target);
  t1.start();
  t2.start();
  t3.start();

或者您可以将字段设为静态,这意味着只有一个实例

private static final AtomicInteger lower = new AtomicInteger(0);
private static final AtomicInteger upper = new AtomicInteger(0);

你遇到的另一个问题是,即使这个程序不是线程安全的,测试失败的窗口也很小,因为输入数据很少会失败。

for(int i = 0; i < 1000000; i++){
    setUpper(i);
    setLower(i);
    if(!invariantSatisfied()){
        System.out.println("False");
    }
}

解决了这个问题。

答案 1 :(得分:0)

当您创建线程时,为每个线程提供Conc类的新实例。这意味着可以同时访问lowerupper个实例变量,每个线程都有自己的变量。 所以这里没有并发问题,更像是算法的问题。 代码是线程安全的。