Объект параметра синхронизированного блока - это объект, на который блокируется блок.Таким образом, все синхронизированные блоки с одним и тем же объектом исключают одновременное выполнение друг друга (и всех синхронизированных методов этого же объекта).
Так что, если у вас есть этот пример
class ExampleA extends Thread() {
public ExampleA(Object l) {
this.x = l;
}
private Object x;
public void run() {
synchronized(x) { // <-- synchronized-block A
// do something
}
}
}
class ExampleB extends Thread() {
public ExampleB(Object l) {
this.x = l;
}
private Object x;
public void run() {
synchronized(x) { // <-- synchronized-block B
// do something else
}
}
}
Object o1 = new Object();
Object o2 = new Object();
Thread eA1 = new ExampleA(o1);
Thread eA2 = new ExampleA(o2);
Thread eB1 = new ExampleB(o1);
Thread eB2 = new ExampleB(o2);
eA1.start(); eA2.start(); eB1.start(); eB2.start();
Теперь у нас есть два синхронизированных блока (A и B, в классах ExampleA
и ExampleB
), и у нас есть два объекта блокировки (o1 и o2).
Еслитеперь мы посмотрим на одновременное выполнение, мы можем видеть, что:
- A1 может выполняться параллельно с A2 и B2, но не с B1.
- A2 может выполняться параллельнодля A1 и B1, но не для B2.
- B1 может выполняться параллельно с A2 и B2, но не для A1.
- B2 может выполняться параллельно с A1 и B1, ноне в A2.
Таким образом, синхронизация зависит только от объекта параметра , а не от выбора блока синхронизации.
В вашем примере, вы используете это:
synchronized(sa){
if(sa.equals("notdone"){
//do some thing on object
}
}
Похоже, вы пытаетесь избежать того, чтобы кто-то изменил вашпеременная позиции sa
в другую строку, когда вы сравниваете ее и работаете - но это не избегает этого.
Синхронизация не работает с переменной , она работает с объектом - ирассматриваемый объект обычно должен быть каким-либо объектом, который содержит переменную (текущий MyThread
объект в вашем случае, достижимый this
), или специальным объектом, используемым только для синхронизации, и который не изменяется.
Как сказал Питер Лоури, строковые объекты обычно являются плохим выбором для блокировок синхронизации, поскольку все равные литералы String являются одним и тем же объектом (то есть исключают синхронизированные блоки друг друга), в то время как одинаковые не-литеральные строки (например, созданные во время выполнения)не является тем же объектом, и, следовательно, не исключает синхронизированные блоки другими такими объектами или литералами, что часто приводит к незначительным ошибкам.