日期:2014-05-20  浏览次数:20693 次

Java多线程之join疑问
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再好好理解理解。

------解决方案--------------------
探讨
嗯,n++不是原子操作我知道。那请问,是不是threads[1].join()执行后,就必须等到threads[1].run()执行完才继续运行程序,也就是进行下一次循环操作,处理threads[2].start();……