所以在这里我编写了三个简单的类来检查多个线程在java中的工作方式,但是每次运行它们都会产生不同的结果。这是代码:
public class Accum {
private static Accum a = new Accum();
private int counter = 0;
private Accum(){}
public static Accum getAccum(){
return a;
}
public void updateCounter(int add){
counter+=add;
}
public int getCount(){
return counter;
}
}//end of class
public class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run() {
for(int x=0; x<98; x++){
//System.out.println("Counter in TWO "+a.getCount());
a.updateCounter(1000);
try{
Thread.sleep(50);
}catch(InterruptedException ex){}
}
System.out.println("one " + a.getCount());
}
}//end of class
public class ThreadTwo implements Runnable{
Accum a = Accum.getAccum();
public void run() {
for(int x=0; x<99; x++){
//System.out.println("counter in Two "+a.getCount());
a.updateCounter(1);
try{
Thread.sleep(50);
}catch(InterruptedException ex){}
}
System.out.println("two "+a.getCount());
}
public class TestThreaad {
public static void main(String[]args){
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}end of class
所以预期的结果是:一个98098,两个98099,但事实证明结果是不可预测的,有时它会是78000或81000,我不知道..
但如果我添加一些代码来打印一行当前的count值,那么最终的结果是正确的。
我真的不知道出了什么问题,甚至在ThreadOne和ThreadTwo,run()方法中添加了关键字synchronized,问题仍然存在......
我已经研究了java 3个月,这是我遇到的最难以解决的问题...所以提前感谢任何人都可以帮助我理解多线程的基本点...
答案 0 :(得分:2)
代码未同步。由于它是非同步的,因此尝试更新计数器的不同Thread
可能同时导致此问题。
如果您同步updateCounter
,则此方法的访问权限将适当。
public synchronized void updateCounter(int add){
counter+=add;
}
答案 1 :(得分:1)
在您的示例中,Accum
实例在线程之间共享。您的更新过程是典型的READ,COMPUTE-UPDATE,WRITE操作序列。由于资源是共享的而不是受保护的,因此这三个操作(来自两个线程 - 进行六次操作)可以以多种不同方式进行交错,从而导致更新丢失。
以下是操作的示例顺序(数字表示线程):
READ #1 -> reads 10
COMPUTE-UPDATE #1 -> computes 1010
READ #2 -> reads 10
WRITE #1 -> writes 1010
COMPUTE-UPDATE #2 -> computes 11
WRITE #2 -> writes 11 (earlier update is lost)
所以你看,几乎任何结果都是可能的。正如@SubhrajyotiMajumder所说,您可以使用synchronized
来修复它。但是如果你这样做,也许线程不适合你的问题;或者,您需要另一个算法过程。
答案 2 :(得分:0)
您的代码未正确同步。
作为synchronized方法的替代方法,我建议使用AtomicInteger
来存储从不同线程访问和修改的变量。