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

时间:2014-10-28 14:24:09

标签: 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));
        }
    }

2 个答案:

答案 0 :(得分:1)

第一个代码

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

第二个代码

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

其他信息

这篇文章解释了第一个解决方案不起作用的原因:Should you synchronize the run method? Why or why not?

答案 1 :(得分:0)

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