我正在阅读最初来自(我相信)IBM developerWorks网站的线程教程。在其中,他们讨论了synced关键字以及实际对象如何锁定同步的代码块,而不是代码块本身。

例如,在作者下面的代码中指出,即使静态类“Thingie”的setLastAccess方法被列为同步方法,但在其下方定义的两个线程仍可以同时调用setLastAccess,因为它们为thingie使用了不同的值。但是,如果事情是静态的,那不意味着他们使用的是相同的值吗?

即使变量名称指向相同的对象,是否也需要仅使用不同的名称?

public class SyncExample {
    public static class Thingie {
        private Date lastAccess;
        public synchronized void setLastAccess(Date date) {
            this.lastAccess = date;
        }
    }
    public static class MyThread extends Thread {
        private Thingie thingie;
        public MyThread(Thingie thingie) {
            this.thingie = thingie;
        }
        public void run() {
            thingie.setLastAccess(new Date());
        }
    }
    public static void main() {
        Thingie thingie1 = new Thingie(),
        thingie2 = new Thingie();
        new MyThread(thingie1).start();
        new MyThread(thingie2).start();
    }
}

最佳答案

您正在将静态方法与静态类混淆。如果setLastAccess是静态方法,则将其标记为synchronized,它将锁定Class中的ClassLoader实例-每个加载程序仅包含其中一个。如果该方法是静态且同步的,则线程将锁定在同一对象上。

但是,在您的示例中,Thingie类被标记为静态,而不是方法。类上的static关键字表示Thingie不受外部SyncExample类的束缚-并不意味着Thingie只有一个实例,并且不影响同步。因此,在您的示例中,当setLastAccess标记为synchronized时,它会锁定类Thingie(this)的实例。由于有两个实例(thingie1thingie2),因此锁位于不同的对象上。显然,如果两个线程都以thingie1传递,则它们都将锁定在同一对象上。

这里是一些阅读:

  • Synchronized methods showing static and instance
  • Nested classes.
  • Synchronized methods
  • 10-06 00:57