public class Letters extends Thread
{
    private String name;
    public Letters(String name)
    {
        this.name=name;
    }
    public void write()
    {
        System.out.println(name);
        System.out.println(name);
    }
    public static void main(String[] args)
    {
        new Letter("X").start();
        new Letter("Y").start();
    }
}
如何保证输出为XXYY或YYXX而不是XYXY或其他的形式?
答案中有一个:
public void run()
{
    synchronized(Letters.class)
    {
        write();
    }
}
但是我认为锁定的对象是Letters字面量,而这个程序中有两个实例,我总觉得这个答案不正确,高手指点了。

解决方案 »

  1.   

    synchronized(Letter.class) 锁定的是Letter类,是一个java.lang.Class类 类型的 对象
    我认为是正确,
    new Letter("X").start();  // thread1
    new Letter("Y").start();  // thread2thread1 申请锁定 Letter.class 对象
    thread2 同样申请 Letter.class 对象因此 thread1 与 thread2 会互斥执行,但无法保证是thread1还是thread2哪个
    先获得 Letter.class 对象锁
    i.e. 能够保证打印出 XXYY 或 YYXX,但无法确定是打印出XXYY 还是 YYXX
    但一定不会出现 XYXY 或 YXYX 等
      

  2.   

    恩,的确是这样。如果你去sync this.name 的话 也是会出现XYXY 或 YXYX.
    因为它同步的只是自己的实例变量.
      

  3.   

    答案是正确的,
    如果这位同学不太明白同步的话你就把这
    synchronized(*.class) 这样的同步看做是一个对静态属性的锁定,
    因为jvm把每个类加载到jvm内都是一个单一的class对象,
    在他建实例时都使用这个class对象来创建实例对象,
    也就是说,在一个jvm环境中只能有一个Letter.class对象,
    这只锁定了这个对象就每次只能有一个线程可以使用它,
    如果下一个线程要进入必须等上一个线程退出后才能进入,
    更简单一点,就像一个静态方法一样,
    所以
    只能有两种情况
    1.new Letter("X").start();
    当这一行代码运行得快的时候输出:XXYY
    2.new Letter("Y").start(); 
    当这行代码运行得快的时候输出:YYXX