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

时间:2016-06-03 05:29:29

标签: java multithreading synchronized

在这个多线程程序中,线程" t1"和" t2"正在尝试在同一个对象obj上执行同步方法printTable()。当t1启动并且从printTable()方法调用run()时,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();  
        }  
}

2 个答案:

答案 0 :(得分:4)

您需要在synchronized指出的printTable()方法中添加关键字Table,如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

答案 1 :(得分:0)

  

为什么不发生这种情况?为什么输出未排序?

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

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

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

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

希望这有帮助。