为什么下面的代码增加2而不是1?(Java新手)
在下面的代码中,在线程运行increment方法后,它将值2输出到控制台。不应该将值设为1,因为方法用1递增?为什么下面的代码增加2而不是1?(Java新手)
class TestSync implements Runnable {
private int balance;
public void run() {
for(int i = 0; i < 50; i++){
increment();
System.out.println(Thread.currentThread().getName() + " balance after increment is " +balance);
}
}
private synchronized void increment() {
int i = balance;
balance = i + 1;
// System.out.println(balance);
}
}
公共类TestSyncTest {
public static void main(String[] args) {
TestSync job = new TestSync();
Thread a = new Thread(job);
Thread b = new Thread(job);
a.setName("Thread A");
b.setName("Thread B");
a.start();
b.start();
}
}
因为你的代码是在循环中。而balance
是全球性的数据。
在第一个循环中,您的balance
的值为1
。
for (int i = 0; i < 50; i++) {
increment();
System.out.println(Thread.currentThread().getName() + " balance after increment is " + balance);
}
OUTPUT
// i balance
// first 0 1
// second 1 2
// third 2 3
// ...
我明白你想要解释的逻辑。print语句输出的是从2开始而不是1开始的值,这就是让我困惑的原因。 –
你可以调试它,让你更容易理解 – KeLiuyue
你的增量方法是同步的,但平衡变量由线程共享。在第一个线程调用增量之后,在可以打印余额之前,另一个线程可以调用增量。将print语句放在increment方法中。
两个线程共享同一个对象。唯一的同步方法会增加i
的值,但不能保证在打印该值时它们将不会为打印它的状态而执行的顺序。
如果您希望每种方法都在增量后打印其值,请从同步方法中取消注释sysout
并将其从run()
中删除。
如果您希望在打印之前完成所有线程,则需要使用Thread.join()。
这里有一个简单的例子:
class TestSync implements Runnable {
private int balance;
public void run() {
for(int i = 0; i < 50; i++){
increment();
}
}
private synchronized void increment() {
int i = balance;
balance = i + 1;
}
public void printBalance() ´{
System.out.println("Balance: " + balance);
}
}
public static void main(String[] args) {
TestSync job = new TestSync();
Thread a = new Thread(job);
Thread b = new Thread(job);
a.setName("Thread A");
b.setName("Thread B");
a.start();
b.start();
try {
System.out.println("Wait for threads to finish.");
a.join();
b.join();
} catch (InterruptedException e) {
System.out.println("Interruption waiting for threads to finish.");
}
a.printBalance(); // either method will print the same value.
}
如果两个线程递增值之前,任何人获得打印出的价值是什么? – tkausl
尝试评论现有的'System.out.println'并取消注释,现在你已经注释掉了。 –
你能检查我的答案吗? – KeLiuyue