Синхронизированное ключевое слово и статические классы в Java - PullRequest
1 голос
/ 18 октября 2011

Я читал учебник по потокам, который изначально был (как мне кажется) с сайта IBM DeveloperWorks.В нем они говорили о ключевом слове synchronized и о том, как синхронизированный блок кода блокируется самим объектом, а не самим блоком кода.

Например, в приведенном ниже коде авторы утверждают, что, хотя метод Thingie статического класса 'setLastAccess указан в списке как синхронизированный, каждый из двух потоков, определенных ниже, может вызывать setLastAccess одновременнопотому что они используют разные значения для штуковин.Но если штука статична, не означает ли это, что они используют одно и то же значение?

Это тот случай, когда имена переменных должны различаться, даже если они ссылаются на один и тот же объект?

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();
    }
} 

Ответы [ 3 ]

6 голосов
/ 18 октября 2011

Вы путаете статический метод со статическим классом .Если бы setLastAccess был статическим методом , то, если он помечен как synchronized, он заблокировал бы экземпляр Class в ClassLoader - для каждого загрузчика существует только один из них.Если бы метод был статическим и синхронизированным, то потоки могли бы блокировать один и тот же объект.

Однако в вашем примере Thingie класс помечен как статический, а не метод.Ключевое слово static в классе означает, что Thingie не привязан к внешнему классу SyncExample - оно не означает, что существует только один экземпляр Thingie иэто не влияет на синхронизацию.Итак, в вашем примере, когда setLastAccess помечен synchronized, он блокируется для экземпляра класса Thingie (this).Поскольку существует два экземпляра (thingie1 и thingie2), то блокировки находятся на разных объектах.Очевидно, что если оба потока были переданы в thingie1, то они оба будут блокироваться на одном и том же объекте.

Вот несколько прочтений:

3 голосов
/ 18 октября 2011

Этот код:

class SomeClass {
    public synchronized void setLastAccess(Date date) {
    }
}

совпадает с:

class SomeClass {
    public void setLastAccess(Date date) {
        synchronized(this) {
        }
    }
}

И этот код:

class SomeClass {
    public static synchronized void setLastAccess(Date date) {
    }
}

совпадает с:

class SomeClass {
    public static void setLastAccess(Date date) {
        synchronized(SomeClass.class) {
        }
    }
}
0 голосов
/ 18 октября 2011

Если синхронизированный метод является методом экземпляра, блокировка выполняется для каждого объекта.поэтому, если у вас есть 2 объекта obj1 и obj2, они могут выполнять методы с заблокированными собственными экземплярами.

Если статический метод синхронизирован, блокировка выполняется для объекта класса.Таким образом, этот метод, как и любые другие статические методы, не может быть выполнен, когда выполняется первый статический синхронизированный метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...