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

标签 java multithreading thread-safety synchronized scjp

有人能解释一下为什么这些代码不输出相同的结果(两个代码之间的唯一区别在于 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 个实例,但它们共享一个对字母对象的引用。因此,如果您锁定此引用,线程将相互排斥并且代码按预期运行。

附加信息

这篇文章很好地解释了为什么第一个解决方案不起作用:Should you synchronize the run method? Why or why not?

关于java - 为什么这个同步方法没有按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26610791/

相关文章:

java - 如何将oracle jdbc驱动程序依赖添加到JIRA插件?

java - 以编程方式更改 Android 中的启动 Logo

c - 如何在内核源代码中设置断点以获取 fork.c 中函数的地址?

c# - 不可重置的 "flags"线程在 C#/.NET 中是否安全?

java - Java 中的多线程控制

java - 从 java 执行外部命令/应用程序

java - Java中的线程与C++中的线程有什么不同?

c++ - 在Linux上的C++中使用线程应该添加哪个头文件

java - 在线程池中执行可运行对象时给定线程不存在

java - 使用 easymock 注入(inject)静态方法/字段?