Java 多线程同步问题
我有这样的代码:Java 多线程同步问题,java,multithreading,synchronization,Java,Multithreading,Synchronization,我有这样的代码: public class OtherClass { // OtherClass public synchronized static void firstMethod() { System.out.println("FIRST METHOD"); } public synchronized static void secondMethod() { System.out.println("SECOND METH
public class OtherClass {
// OtherClass
public synchronized static void firstMethod() {
System.out.println("FIRST METHOD");
}
public synchronized static void secondMethod() {
System.out.println("SECOND METHOD");
// In actual code I would have try catch for this but here I just didn't
// include it
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class MainClass {
// main method of MainClass
public static void main(String args[]) {
Thread firstThread = new Thread() {
public void run() {
while (true) {
OtherClass.firstMethod();
}
}
};
Thread secondThread = new Thread() {
public void run() {
while (true) {
OtherClass.secondMethod();
}
}
};
secondThread.start();
firstThread.start();
}
}
我首先启动第二个线程的原因是,我希望首先执行OtherClass
的secondMethod
。我应该每5秒查看控制台输出中的“第一种方法”
和“第二种方法”
。原因是,由于Thread.sleep
没有放弃锁,第一个线程在5秒钟内没有访问第一个方法的权限,因为第二个线程在类上有一个锁,而第二个线程在第二个方法中告诉线程睡眠5秒钟。但我得到了意想不到的结果。我在控制台输出中得到的只是每5秒一次的“第二种方法”。不会调用firstMethod
。忽略代码中的编译问题
那只是巧合。线程调度程序只是决定继续执行第二个线程,该线程太快地重新获取了锁
运行足够长的时间(或者缩短睡眠时间以获得更快的结果),您将看到另一个方法被调用。忽略代码中的编译问题
那只是巧合。线程调度程序只是决定继续执行第二个线程,该线程太快地重新获取了锁
运行足够长的时间(或者缩短睡眠时间以获得更快的结果),您将看到另一个方法被调用。您的处理器不会同时执行线程;它将在每次运行第一个线程时运行第二个线程 行为很清楚:处理器执行第二个线程。然后,处理器执行第一个线程,并看到它被第二个线程锁定。5秒后,再次调用第二个线程。它生成输出,释放锁并再次锁定。如果您的第一个线程再次被调用,它将再次被锁定
要解决此问题,请在while结束时添加
Thread.yield()
。这将使处理器在继续执行第二个线程之前调用第一个线程(第一个线程不是唯一被调用的线程,它只是将第二个线程从执行中删除一次)。然后第一个线程获得锁,等待5秒钟,输出并调用thread.yield()
;然后你的第二个线程再次获得锁,依此类推。你的处理器不会同时执行你的线程;它将在每次运行第一个线程时运行第二个线程
行为很清楚:处理器执行第二个线程。然后,处理器执行第一个线程,并看到它被第二个线程锁定。5秒后,再次调用第二个线程。它生成输出,释放锁并再次锁定。如果您的第一个线程再次被调用,它将再次被锁定
要解决此问题,请在while结束时添加Thread.yield()
。这将使处理器在继续执行第二个线程之前调用第一个线程(第一个线程不是唯一被调用的线程,它只是将第二个线程从执行中删除一次)。然后第一个线程获得锁,等待5秒钟,输出并调用thread.yield()
;然后第二个线程再次获得锁,以此类推
我首先启动第二个线程的原因是,我希望首先执行OtherClass的第二个方法
线程不是这样工作的。这不是线程的用途。线程不保证先发生什么,除非在它们之间提供显式同步;一般来说,使用的同步越多,多线程的好处就越少
在您的示例中,您有显式的同步,可以防止firstMethod()和secondMethod()的任何并发执行,但是您没有任何东西可以保证哪个将首先运行,哪个将第二次运行。main()很可能会在它们运行之前终止。在这一点上,由调度器选择何时运行哪一个。不需要按照代码调用其start()方法的相同顺序启动它们
您的示例可能具有教育意义,但它也是不使用线程的示例。你的同步非常繁重。您的程序基本上做两件事,firstMethod()和secondMethod(),同步确保它们不会重叠。在生产软件中,如果有两个任务不能重叠,那么如果它们总是由同一个线程执行,则可以简化程序的逻辑
我在控制台输出中得到的只是每5秒一次的“secondmethod”。没有调用第一个方法
你的问题在我看到之前已经编辑好了,所以我不知道你说的是原始版本,还是固定版本。但无论如何:
程序中的同步不能保证两个线程轮流运行。它所做的只是防止它们同时打印
您的每个线程都运行一个循环,该循环获取锁、打印某些内容、释放锁,然后立即尝试再次获取锁。当一个正在运行的线程释放一个锁,然后立即尝试再次获取它时,它很可能会成功。其他线程是否在等待锁并不重要。操作系统不知道您的程序试图完成什么,但它知道它可以通过让一个线程继续运行而不是阻塞它和取消阻塞其他线程来更有效地利用CPU
您需要使用一些额外的同步来使线程轮换,但正如我所说的,在实际程序中,使用的同步越多,使用线程的好处就越少
我首先启动第二个线程的原因是,我希望首先执行OtherClass的第二个方法
线程不是这样工作的。这不是线程的用途。苏氨酸