为什么这个 Java 程序中的线程没有同步访问该方法?

Why is the method not accessed synchronously by the threads in this Java program?

在这个多线程程序中,线程"t1"和"t2"正试图在同一个对象obj上执行同步方法printTable()。当 t1 启动并从其 run() 方法调用 printTable() 时,t2 必须等待直到 t1 完成同步方法的执行;为什么这没有发生?为什么输出未排序?

程序如下:

class Table{  
        void printTable(int n){//synchronized method  
            for(int i=1;i<=5;i++){  
                System.out.println(n*i);  
                try{  
                    //Thread.sleep(400);  
                }catch(Exception e){System.out.println(e);}  
            }  
        }  
}  

public class TestSynchronization3{  
    public static void main(String args[]){  
        final Table obj = new Table();//only one object  
            Thread t1=new Thread(){  
                public void run(){  
                    obj.printTable(5);  
                }  
            };  
            Thread t2=new Thread(){  
                public void run(){  
                    obj.printTable(100);  
                }  
            };  
            t1.start();  
            t2.start();  
        }  
}

您需要在 class Table 中的 printTable() 方法之前添加关键字 synchronized,正如 Michael 指出的那样。将函数的签名从

更改为 printTable()
 void printTable(int n){...}

 synchronized void printTable(int n){...}

这将产生如下输出:

100
200
300
400 
500
5
10
15
20
25

5  
10  
15  
20  
25  
100  
200  
300  
400  
500

why is this not happening? Why is the output unsorted?

虽然,正如其他评论和答案所提到的,您需要使用 synchronized 关键字,但我怀疑您真正的问题是您不了解线程的竞争条件。

仅仅因为您在代码中的 obj.printTable(100); 线程之前启动了 obj.printTable(5); 线程,这并不能确保线程 运行 的顺序。正如 @user5794376 所展示的,当两个线程启动时,会进行一场竞赛,看谁第一个调用 printTable(...),然后谁必须等待另一个线程完成。异步线程 运行,无法预测哪一个会获胜并保证顺序。

如果您需要强制输出顺序,那么问题就变成了,除非这是某种学术练习,否则为什么要使用线程。线程的全部意义在于它们 运行 并行、异步。任何用于控制其操作顺序的措施(如锁定或信号)都会使它们的整个目的无效。

另一件可以尝试的事情是 运行 printTable(...) 从完全没有同步的两个线程。 System.out.println(...) 是一种同步方法,所以很好。然而,您可能会看到相同的输出,因为在另一个线程开始之前,一个线程正在获取并 运行ning 通过它的所有 5 个 println(...) 语句。如果您真的想看到交错,那么您应该将 5 增加到 5000000。然后您应该看到一个 *5 输出块,然后是一个 *100 输出块。

希望这对您有所帮助。