本帖最后由 周兴中 于 2012-6-24 03:34 编辑
由于你操作共享数据时没有进行同步处理,使得balance在被进行加减操作时,出现被多加或者多减的情况,当运行次数足够多时,很容易出现不一样的结果.
例如:
balance = balance + num; 假设此时 balance为1000,num为20
在balance还没有被赋值时, 此时balance仍为1000,被b线程抢走了执行权.
执行了这句 balance = balance - num; 此时balance为980
然后当a线程再次拿到执行权时,它仍认为balance为1000,赋值后结果为1020 ,结果错误.
例2
public class MyThread extends Thread
{
public static int n = 0;
public void run()
{
int m = n;
yield();
m++;
n = m;
}
public static void main(String[] args) throws Exception
{
MyThread myThread = new MyThread ();
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
threads = new Thread(myThread);
for (int i = 0; i < threads.length; i++)
threads.start();
for (int i = 0; i < threads.length; i++)
threads.join();
System.out.println("n = " + MyThread.n);
}
}
由于先调用了thread1的start方法,因此,thread1的run方法一般会先运行。当thread1的run方法运行到第一行(int m = n;)时,将n的值赋给m。当执行到第二行的yield方法后,thread1就会暂时停止执行,而当thread1暂停时,thread2获得了CPU资源后开始运行(之前thread2一直处于就绪状态),当thread2执行到第一行(int m = n;)时,由于thread1在执行到yield时n仍然是0,因此,thread2中的m获得的值也是0。这样就造成了thread1和thread2的m获得的都是0。在它们执行完yield方法后,都是从0开始加1,因此,无论谁先执行完,最后n的值都是1,只是这个n被thread1和thread2各赋了一遍值。这个过程如下图如示:
所以,当对共享数据进行写操作时,要进行数据同步,数据同步就是指在同一时间,只能由一个线程来访问被同步的类变量,当前线程访问完这些变量后,其他线程才能继续访问。
你的代码要想得到正确的结果,可以简单的在add和 withdraw 方法前加 synchronized修饰. 即可同步
|