Java线程问题?

时间:2016-05-28 09:37:40

标签: java multithreading

我想知道为什么结果不是400 000.有两个线程为什么会被阻止?

class IntCell {
    private int n = 0;
    public int getN() {return n;}
    public void setN(int n) {this.n = n;}
}
class Count extends Thread {
    private static IntCell n = new IntCell();
    @Override public void run() {
        int temp;
        for (int i = 0; i < 200000; i++) {
            temp = n.getN();
            n.setN(temp + 1);
        }
    }
    public static void main(String[] args) {
        Count p = new Count();
        Count q = new Count();
        p.start();
        q.start();
        try { p.join(); q.join(); }
        catch (InterruptedException e) { }
        System.out.println("The value of n is " + n.getN());
    }
}

为什么会出现这样的问题?

3 个答案:

答案 0 :(得分:6)

因为增加变量的方式不是原子操作,实际上是为了增加它:

  1. 获取上一个值
  2. 为此值添加一个
  3. 设置新值
  4. 他们是3个以原子方式完成的操作,您应该使用 webView.loadUrl(urlToLoad); if (!isConnected(getActivity())) { Toast.makeText(getActivity(), "You are offline ", Toast.LENGTH_SHORT).show(); } /** * Check if there is any connectivity * * @param context * @return is Device Connected */ public static boolean isConnected(Context context) { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); if (null != cm) { NetworkInfo info = cm.getActiveNetworkInfo(); return (info != null && info.isConnected()); } return false; } 阻止或使用synchronized代替。

    使用AtomicInteger块,它将类似于:

    synchronized

    使用synchronized (n) { temp = n.getN(); n.setN(temp + 1); } ,您需要重新编写代码:

    AtomicInteger

    使用class IntCell { private final AtomicInteger n = new AtomicInteger(); public int getN() {return n.get();} public void incrementN(int n) {this.n.addAndGet(n);} } for (int i = 0; i < 200000; i++) { n.incrementN(1); } 的方法是非阻塞的,因此它会更快

答案 1 :(得分:2)

这里的问题是你允许竞争条件。考虑循环内的块:

$('#xxx').unbind();
$('#xxx').off();
$('#xxx').sendkeys('123'); // but again nothing happens

代码上下文在您获得当前N的时间和增加它的时间之间切换,使您设置“旧”值。解决此问题的一种方法是确保循环的内部部分在同步块中运行:

temp = n.getN();
n.setN(temp + 1);

答案 2 :(得分:2)

当两个线程同时访问一个对象时,它们会相互干扰,结果不确定。例如,假设p读取n的值并得到0,然后q读取相同的值并得到0,然后p将值设置为1和q也将其设置为1(因为它仍然认为它的值为0)。现在n的值增加1,即使两个计数器“递增”一次。您需要使用synchronized块来确保计数器不会相互干扰。有关详情,请参阅https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html