- Java code
public class Test extends Thread{ public static volatile int n = 0; public void run() { for (int i = 0; i < 10; i++, n++) try { sleep(1); // 为了使运行结果更随机,延迟3毫秒 } catch (Exception e) { } } public static void main(String[] args) throws Exception { Thread threads[] = new Thread[100]; for (int i = 0; i < threads.length; i++) // 建立100个线程 threads[i] = new Test(); for (int j = 0; j < threads.length; j++) // 运行刚才建立的100个线程 { threads[j].start(); threads[j].join(); } System.out.println("n=" + Test.n); }}
结果为:1000
- Java code
public class Test extends Thread{ public static volatile int n = 0; public void run() { for (int i = 0; i < 10; i++, n++) try { sleep(1); // 为了使运行结果更随机,延迟3毫秒 } catch (Exception e) { } } public static void main(String[] args) throws Exception { Thread threads[] = new Thread[100]; for (int i = 0; i < threads.length; i++) // 建立100个线程 threads[i] = new Test(); for (int j = 0; j < threads.length; j++) // 运行刚才建立的100个线程 { threads[j].start(); } for (int k = 0; k < threads.length; k++) // 100个线程都执行完后继续 threads[k].join(); System.out.println("n=" + Test.n); }}
结果接近1000.大多数为900到998之间,很不确定。
请问这是神马原因啊?
------解决方案--------------------------------------------------------
[del][/del]第一种情况
threads[j].start();
threads[j].join();
两个是连在一起的,所以start方法启动后,就开始jion,就会等待j线程结束,才进入下一个for循环
第二种情况
threads[j].start();
...
threads[k].jion();
线程调用start后,什么时候执行由CPU决定,所以在进入k循环之前,j线程可能有一部分就随机执行了,等到进入k循环的时候,k线程jion有一部分已经失去意义,因为有些j线程早已执行结束,所以造成数据不同步
------解决方案--------------------------------------------------------
n++相当于n = n + 1;
这样的操作是由几个指令来完成的
首先从内存中读取n的值,放到寄存器中,然后对寄存器的操作数执行+1,然后再把寄存器的结果写入n的内存中
那么好了,多个线程执行,假如线程1线从n的内存读取n的值,开始n的值为0(线程1的寄存器的值是0),然后线程1没来得及执行后面的操作CPU就被收回,假设这时线程2获得CPU权限执行,那么线程2也会从n的内存读入n的值,然后执行操作直到n=10(此时n的内存的值是10),然后线程2的CPU权限被收回,然后假设此时线程1又获得了CPU权限执行,那么,刚才知道,线程1的寄存器的值是0,然后执行后面+1操作,然后把寄存器的值写入n的内存,可见,此时n的内存的值又变回了1,也就是说线程1的n并不是在线程2的n的基础上进行累加的,而是在自己读入的n的值的基础上进行累加的,所以这样就造成了结果少了线程2累加的10
正是因为多线程的操作会引起这样的不同步问题,才有了synchronized这样的同步解决方案。LZ再好好理解理解。
------解决方案--------------------------------------------------------