我想知道为什么结果不是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());
}
}
为什么会出现这样的问题?
答案 0 :(得分:6)
因为增加变量的方式不是原子操作,实际上是为了增加它:
他们是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。