我试图理解并发编程,但我不确定有一件事。我有一个程序,它有两个线程,它们增量相同的int (IntCell n)。在200,000循环之后,int应该是400,000,但它超过了20万。现在我想知道其中一个线程是否被征用了,当第二个线程正在递增它时,或者它们只是一个一个地读取相同的值,然后增量它并将它设置为int 2次(设置相同int的两个操作)。下面是代码:
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());
}
}发布于 2019-01-23 10:25:11
两个线程都可以将static IntCell n的值复制到它们的线程本地存储中。
使用volatile关键字向线程发出信号,以同步线程本地值和共享值。
static volatile IntCell n另一个问题是原子性不佳,即:
// Thread 1 // Thread 2
temp = n.getN();
temp = n.getN();
n.setN(temp + 1);
n.setN(temp + 1);对于共享的n,这将增加n而不是2,而只是1。
synchronize (n) {
temp = n.getN();
n.setN(temp + 1);
}这确保了与n关联的信号量上的关键区域阻塞。
发布于 2019-01-23 10:27:11
您没有使用任何类型的同步,这导致了两个主要问题:
n的当前值读取到temp和写入递增的值之间存在一个争用条件,另一个线程可以在两者之间修改该值,然后重写该值。可能的解决方案包括使用synchronized-blocks、包java.util.concurrent.locks中的锁或支持原子更新的类型(如AtomicInteger )。
https://stackoverflow.com/questions/54324716
复制相似问题