为什么这个同步方法没有按预期工作?

有人可以解释两个我为什么这些代码不输出相同的结果(两个代码之间的唯一区别在于run()方法)?

注意:第一个代码似乎没有做任何锁定!

第一个代码:

class LetterThread extends Thread { private StringBuffer letter; public static void main(String[] args) { StringBuffer sbltr = new StringBuffer("A"); LetterThread one = new LetterThread(sbltr); LetterThread two = new LetterThread(sbltr); LetterThread three = new LetterThread(sbltr); one.setName("Thread ONE"); two.setName("Thread TWO"); three.setName("Thread THREE"); one.start(); two.start(); three.start(); } LetterThread(StringBuffer letter) { this.letter = letter; } public synchronized void run() { { for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName() + " (" + x + ") = " + letter); } letter.setCharAt(0, (char) (letter.charAt(0) + 1)); } } } 

第二个代码:此代码正如预期的那样工作

 class LetterThread extends Thread { private StringBuffer letter; public static void main(String[] args) { StringBuffer sbltr = new StringBuffer("A"); LetterThread one = new LetterThread(sbltr); LetterThread two = new LetterThread(sbltr); LetterThread three = new LetterThread(sbltr); one.setName("Thread ONE"); two.setName("Thread TWO"); three.setName("Thread THREE"); one.start(); two.start(); three.start(); } LetterThread(StringBuffer letter) { this.letter = letter; } public void run() { synchronized (letter) { for (int x = 0; x < 100; x++) { System.out.println(Thread.currentThread().getName() + " (" + x + ") = " + letter); } letter.setCharAt(0, (char) (letter.charAt(0) + 1)); } } 

第一码

问题是你有3个线程实例,每个线程运行它自己的方法run()synchronized实例。 但总是只有一个线程正在与它自己的run()方法同步,因此它会在线程希望它运行时运行。 这导致完全没有同步。

第二码

您还有3个线程实例,但它们共享对字母对象的引用 。 因此,如果您锁定此引用,则线程将相互排除,代码将按预期运行。

附加信息

这篇文章解释了为什么第一个解决方案不起作用的原因: 你应该同步run方法吗? 为什么或者为什么不?

如果要同步两个线程,则必须由所有线程锁定共享资源。 在run方法(或线程类中的任何实例方法)中进行同步,每个线程锁定它自己的方法,导致根本没有同步。