同步线程方法同时执行 – 为什么?

我有一个关于线程的问题。 我有跟随Thread类并创建2个线程对象。

public class MyThread extends Thread{ String name=""; public MyThread(String string) { name=string; } @Override public void run() { callMe(); } synchronized private void callMe() { System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(name+" = "+i); } } public static void main(String[] args) { MyThread a = new MyThread("A"); MyThread b = new MyThread("B"); a.start(); b.start(); } } 

当我执行此操作时,我得到的输出是 –

 Started Started B = 1 B = 2 A = 1 A = 2 B = 3 A = 3 B = 4 A = 4 B = 5 A = 5 

我知道随着线程调度程序选择A和B随机打印。

但我的问题是:为什么循环不是一个接一个地执行? 我使用了synchronized关键字。

您的synchronized方法是有效的:

 private void callMe() { synchronized(this) { System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(name+" = "+i); } } } 

现在你已经创建了两个不同的实例,所以每个线程都会有所不同......因此它们不会相互同步。 如果你想看到两个线程使用同一个监视器,你可以像这样重写你的代码:

 public final class DemoRunnable implements Runnable { @Override public synchronized void run() { System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(Thread.currentThread().getName() + " = " + i); } } public static void main(String[] args) { Runnable runnable = new DemoRunnable(); Thread a = new Thread(runnable, "A"); Thread b = new Thread(runnable, "B"); a.start(); b.start(); } } 

然后你会得到这样的输出:

 Started A = 1 A = 2 A = 3 A = 4 A = 5 Started B = 1 B = 2 B = 3 B = 4 B = 5 

(当然,它可能是相反的方式。)

我们仍然有两个线程,但它们在同一个对象上调用一个synchronized方法(在这种情况下是一个DemoRunnable ),因此必须等待另一个完成。

几点:

  • 实现Runnable通常比扩展Thread ; 它更灵活
  • Thread对象上进行同步有自己的问题,因为Thread类本身就是这样做的; 尽量避免它
  • 就个人而言,我不喜欢同步this - 我通常会有一个Object类型的私有final变量来表示只有我的代码知道的监视器...这样我就可以很容易地看到所有可以在其上同步的代码,这使得更容易推理

每个对象同步工作。 要跨实例进行同步,您需要一个共享对象来进行同步。

 private final static Object globalLock = new Object(); // Later private void callMe() { synchronized (globalLock) { System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(name+" = "+i); } } } 

您的准则与本准则相同

  private void callMe(){ synchronized(this){ System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(name+" = "+i); } } } 

您只需同步到当前对象。 如果要将它们彼此同步,则需要同步到类,如下所示:

 private void callMe(){ synchronized(MyThread.class){ System.out.println("Started"); for (int i = 1; i <= 5; i++) { System.out.println(name+" = "+i); } } } 

因为2个线程正在通过2个不同的对象执行。

好吧,你现在必须从其他答案中实现。 您正在创建2个单独的对象,即。 a和b。 现在,当您调用start方法时,将启动一个新线程,以通过相应(单独的不相同)对象的run方法执行。 同步确实在方法上,但是只有一个线程在a的callMe方法中运行,并且只有一个线程通过b的callMe方法运行。 所以你期望输出应该是:

A – 1 A – 2 A – 3 ……

没有发生。

希望这可以帮助