为什么这个 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
输出块。
希望这对您有所帮助。
在这个多线程程序中,线程"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
输出块。
希望这对您有所帮助。