[英]Threads - simple concurrency issue
好的,这就是问题所在:以下代码显然不是线程安全的,导致方法increment()未同步。 输出会有所不同,并且不会像这样:1,2,3,4,5,6 ...
例如,输出可能是这样的:1,2,3,4,5,1 ...,然后它像这样继续6,7,8,...并达到100。我不知道它怎么能达到100,不应该在秒1之后再来2,至少在某些情况下,原因是其他线程错误地更新了余额。 问题是这样的:为什么在1之后,它通常会继续以6、7 ...
class Job implements Runnable{
private int balance;
public void run(){
for (int i = 0; i < 50; i++) {
increment();
System.out.println(balance);
int a = 3;
int b = 4;
a = b;
}
}
public void increment(){
int i = balance;
balance = i+1;
}
}
public class ThreadsDemo{
public static void main(String[] args) {
Job job = new Job();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("alpha");
beta.setName("beta");
alpha.start();
beta.start();
}
}
为了进一步解释,这是可能的结果之一:
线程1:余额-0
i-0(线程1恢复为可运行状态)
线程2:
余额-0、1、2、3、4、5
i-0、1、2、3、4(线程2恢复为可运行状态)
线程1(进入运行状态):balance-... 1,2
我-0、1
(在某些情况下,它可以正常更新,但在50次迭代中必须进行一些异常更新)每个结果如何达到100,这是某种IDE优化来处理线程交织还是什么?
答案:因此,在此示例中无需闩锁,只需线程在打印中“阻塞”,而另一个线程可以同时完成更新。 泰·艾菲
class Job implements Runnable{
public int balance = 0;
//public static CountDownLatch latch = new CountDownLatch(1);
public void run(){
for (int i = 0; i < 50000; i++) {
increment();
}
}
public void increment(){
int i = balance;
balance = i+1;
}
}
public class ThreadsDemo{
public static void main(String[] args) {
Job job = new Job();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("alpha");
beta.setName("beta");
alpha.start();
beta.start();
try {
alpha.join();
beta.join();
} catch (Exception ex) { }
System.out.println(job.balance +" "+ alpha.isAlive() + " " + beta.isAlive());
}
}
正如预期的那样,产量约为60 000。
您的计算非常快,启动线程非常慢。 第一个完全在第二个开始之前完成。 输出中的异位数字可能只是操作系统中缓冲区刷新的问题。
添加一个锁存器,以便两个线程实际上同时启动,并使用足够大的数字,您将看到总计没有加起来。
public static CountDownLatch latch = new CountDownLatch(1);
private static class Job implements Runnable{
private int balance;
public void run(){
try {
latch.await();
} catch (InterruptedException e) {}
for (int i = 0; i < 50000; i++) {
//existing code
}
}
public void increment(){
int i = balance;
//make it work harder so there's more opportunity for an actual interleave
balance = new BigInteger(Integer.toString(i)).add(BigInteger.ONE).intValue();
}
}
public static void main(String[] args) {
//existing code
alpha.start();
beta.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
latch.countDown();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.