麻烦帮忙看看如下的程序,为什么对sum_thread2的同步完全没有起到作用呢?谢谢。 package multiThread; /* 
 * Still use the first way to write a thread 
 * Has mistake in this code 
 */ 
public class moreMultiThreadExamples implements Runnable { 
     
    private double sum = 0; 
    private double [] f1; 
    private double [] f2; 
    private int vectorLength = 100000; 
    private double sum_thread1 = 0; 
    private Double sum_thread2 = 0.0; 
     
    public void run() { 
        synchronized( sum_thread2 ) { 
            for( int i = f1.length / 2 ; i < f1.length ; i ++ ) { 
                //System.out.println( "f1[" + i + "]=" + f1[i] + "," + "f2[" + i + "]=" + 
 f2[i]); 
                sum_thread2 += f1[i] * f2[i]; 
            } 
        } 
    } 
     
    public void vectorMultiplicationMultiThread() { 
        Thread mythread = new Thread( this ); 
        mythread.start(); 
        for( int i = 0 ; i < f1.length / 2 ; i ++ ) { 
            //System.out.println( "f1[" + i + "]=" + f1[i] + "," + "f2[" + i + "]=" +  
f2[i]); 
            sum_thread1 += f1[i] * f2[i]; 
        } 
/*此处,不等mythread结束就会接着算出sum然后打印输出,所以导致结果不对*/ 
        synchronized( this.sum_thread2 ) { 
            sum = sum_thread1 + sum_thread2; 
        } 
        System.out.println( sum ); 
    } 
     
    public void vectorMultiplicationSingleThread() { 
        sum = 0; 
        for( int i = 0 ; i < f1.length ; i ++ ) { 
            //System.out.println( "f1[" + i + "]=" + f1[i] + "," + "f2[" + i + "]=" +  
f2[i]); 
            sum += f1[i] * f2[i]; 
        } 
        System.out.println( sum ); 
    } 
     
    public void init() { 
        f1 = new double [vectorLength]; 
        f2 = new double [vectorLength]; 
        java.util.Random rd = new java.util.Random(System.currentTimeMillis());  
        for( int i = 0 ; i < f1.length; i ++ ) { 
            f1[i] = rd.nextDouble(); 
            f2[i] = rd.nextDouble(); 
        } 
    } 
    public static void main(String [] args) { 
        moreMultiThreadExamples myexample = new moreMultiThreadExamples(); 
        myexample.init(); 
         
        long starttime = System.currentTimeMillis(); 
        myexample.vectorMultiplicationSingleThread(); 
        long endtime = System.currentTimeMillis(); 
        System.out.println( "Single thread:" + (endtime - starttime) + "ms" ); 
                 starttime = System.currentTimeMillis(); 
        myexample.vectorMultiplicationMultiThread(); 
        endtime = System.currentTimeMillis(); 
        System.out.println( "Multi thread:" + (endtime - starttime) + "ms" ); /*        Thread mythread = new Thread(myexample); 
        mythread.start(); 
        for( int i = 0 ; i < myexample.f1.length / 2 ; i ++ ) { 
            //System.out.println( "f1[" + i + "]=" + f1[i] + "," + "f2[" + i + "]=" +  
f2[i]); 
            myexample.sum_thread1 += myexample.f1[i] * myexample.f2[i]; 
        } 
        synchronized( myexample.sum_thread2 ) { 
            myexample.sum = myexample.sum_thread1 + myexample.sum_thread2; 
        } 
        System.out.println( myexample.sum ); */ 
    } 

解决方案 »

  1.   

    线程本来就是并发的,当一个线程start之后如不做特别处理,本来就无法确保原线程中的后续代码一定在新启动线程结束后才执行。要做到这一点,可以用join()方法强制等待新启线程结束
                    ......
    mythread.start();
                    // 在这个地方加入下面代码
    try {
    mythread.join();
    } catch (Exception e) {
    }
      

  2.   

    join()是强制父进程等待子进程结束的作用是吗?
      

  3.   

    主要是因为你同步的是Object类型的变量 ~ 这个变量你赋值的时候会替换掉原变量,所以你的synchronized是没用的, 最好自己建一个变量Object lock = new Object(); 最高同步synchronized(lock)这个变量
      

  4.   

    个人不建议使用JOIN~ 那样的话 就不是多线程了
      

  5.   

    在 LZ 的程序中 synchronized 其实是起作用的,只是程序并不能保证是主线程先进入 synchronized 域,还是 myThread 先进入 synchronized 域。用 join 是一种解决方案。并不能说用 join 就不是多线程了。join 是用来解决多线程中类似这样的问题的。像 LZ 这样的问题,也只能通过 join 这样的方式去解决不是么?因为你必须等另外一个线程给你一个结果。
      

  6.   

    恩~ 他上面写的程序 一般都是会子线程先获取到同步锁~ 但是为了更确定程序是否运行完成 不一定需要用JOIN, 也可以用同步状态位  如一共有10个子线程 当每个子线程执行完成时对状态为+1, 最后总结过在状态为10时才执行
      

  7.   

    当然可以。异曲同工。给你个例子看看,不要误会了 join :                Thread mythread = new Thread(new Runnable(){public void run() {
    //do anything,maybe have a long time.
    };});  
    mythread.start();  

    //do anything,maybe have a long time.
    // flag 1
    try {
    mythread.join();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    //use result of mythread run
    // flag 2主线程先启动了一个子线程 mythread ,并且随即让其运行。然后主线程在 flag 1 处进行一个耗时的运算。然后,他要等待 mythread 的运行结果。