synchronized(Foo.Class){
//some code..
}
Заблокирует ли это все экземпляры класса Foo или только статические методы/поля?Что делает синхронизация (ссылка класса)?
synchronized(Foo.Class){
//some code..
}
Заблокирует ли это все экземпляры класса Foo или только статические методы/поля?Что делает синхронизация (ссылка класса)?
Он входит в монитор для объекта Foo.class
. Если другой метод также синхронизируется на Foo.Class
, ему придется подождать, считая, что он находится в другом потоке.
Если метод не синхронизируется с ним, он не будет затронут, независимо от того, является ли он статическим или нет. Не то, что синхронизированные статические методы неявно синхронизируются с объектом класса для класса, где они были определены.
Он синхронизирует доступ к методам/синхронизированным предложениям, которые его используют. Это могут быть методы класса Bar - не обязательно Foo.
Важно то, что все методы/синхронизированные предложения, которые синхронизируются на «Foo.class», взаимно исключаются из одновременного выполнения.
Синхронизация вообще не влияет на поля - нет способа объявить поле синхронизированным.
Мое толкование 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 держит экземпляр блокировки я думаю, что это показывает, что статический замок не блокирует все экземпляры класса.
Он не блокирует никаких членов. Он ничего не блокирует. Он * синхронизирует * с объектом класса. – EJP
Синхронизация объекта класса работает точно так же, как синхронизация экземпляра. Класс, такой как 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 является концом фигурного скобки }
).
@Chandana - Неверно. –