2013-03-31 2 views

ответ

6

Он входит в монитор для объекта Foo.class. Если другой метод также синхронизируется на Foo.Class, ему придется подождать, считая, что он находится в другом потоке.

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

0

Он синхронизирует доступ к методам/синхронизированным предложениям, которые его используют. Это могут быть методы класса Bar - не обязательно Foo.

Важно то, что все методы/синхронизированные предложения, которые синхронизируются на «Foo.class», взаимно исключаются из одновременного выполнения.

Синхронизация вообще не влияет на поля - нет способа объявить поле синхронизированным.

-1

Мое толкование tutorialsynchronized(Foo.class) {...} будет блокировать только статические элементы класса. Но, конечно, вам нужно написать тест.

public class SyncTest { 
    public static SyncTest instance; 
    public static String valueA; 
    public String valueB; 

    public static void main(String[] args) { 
     instance = new SyncTest(); 

     (new Thread(new Task1())).start(); 
     (new Thread(new Task2())).start(); 
     try { 
      Thread.sleep(10000); 
      synchronized(SyncTest.class) { 
       System.out.println("Value A: " + valueA); 
      } 
      synchronized(instance) { 
       System.out.println("Value B: " + instance.valueB); 
      } 
     } catch (InterruptedException interrupt) { } 
    } 
} 

class Task1 implements Runnable { 
    public void run() { 
     try { 
      synchronized(SyncTest.class) { 
       System.out.println("Task 1 Sleeping "); 
       Thread.sleep(500); 
       SyncTest.valueA = "One"; 
       System.out.println("T1 A: " + SyncTest.valueA); 
      } 

      synchronized(SyncTest.instance) { 
       Thread.sleep(1000); 
       SyncTest.instance.valueB = "Two"; 
       System.out.println("T1 B: " + SyncTest.instance.valueB); 
      } 
     } catch (InterruptedException interrupt) { } 
     System.out.println("Task 1 Finished "); 
    } 
} 

class Task2 implements Runnable { 
    public void run() { 
     System.out.println("Task 2 Started"); 
     try { 
      Thread.sleep(1000); 
      synchronized(SyncTest.class) { 
       SyncTest.instance.valueB = "Four"; 
       System.out.println("T2 B: " + SyncTest.instance.valueB); 

       Thread.sleep(5000); 

       SyncTest.valueA = "Three"; 
       System.out.println("T2 A: " + SyncTest.valueA); 
      } 
     } catch (InterruptedException interrupt) { } 
     System.out.println("Task 2 Finished"); 
    } 
} 

Что дает выход:

Task 1 Sleeping 
Task 2 Started 
T1 A: One 
T2 B: Four 
T1 B: Two 
Task 1 Finished 
T2 A: Three 
Task 2 Finished 
Value A: Three 
Value B: Two 

как задача 2 обновления valueB в то время как задача 1 держит экземпляр блокировки я думаю, что это показывает, что статический замок не блокирует все экземпляры класса.

+0

Он не блокирует никаких членов. Он ничего не блокирует. Он * синхронизирует * с объектом класса. – EJP

1

Синхронизация объекта класса работает точно так же, как синхронизация экземпляра. Класс, такой как Foo.class, является объектом и, следовательно, имеет встроенный монитор. Код, указанный вами:

synchronized(Foo.Class){ 
    //some code.. 
} 

синхронизирует доступ к классу Foo. Это может быть полезно при попытке синхронизации статических переменных класса. Например:

public class Foo{ 

    private static int COUNTER = 0; 

    synchronized public static void increment(){ 

     COUNTER ++; 
    } 

    public static void decrement(){ 
     synchronized (Foo.class) { 

      COUNTER ++; 
     } 
    } 
} 

Как вы можете видеть, что синхронизация Foo.class может быть достигнуто одинаково, как для любого экземпляра. При попытке синхронизации блока кода экземпляра используется: synchronized(this){}, что эквивалентно synchronized(Foo.class){} в случае объекта класса. То же самое относится и в случае синхронизированных методов: synchronized public void increment(){} эквивалентно: synchronized public static void increment(){}

Теперь по поводу вашего вопроса:

ли это блокирует все экземпляры класса Foo или только это статические методы/поля?

Конечно, он не приобретает блокировки всех случаев, как описано выше. Более того, объект класса не знает созданных экземпляров. Блок synchronized не блокирует поле.Он блокирует только блок кода/метода, который должен быть выполнен как атомная операция потоком, который приобрел эту блокировку, и ни один другой поток не может ввести этот блок кода (но может выполнять другие блоки, если они не синхронизированы), пока первая нить освобождает замок (который на Java является концом фигурного скобки }).

Смежные вопросы