Предположим, что мы имеем следующий класс
class Class1 {
public void Method1() {
synchronized(myobject) {
/* some code */
}
}
}
где myobject - это экземпляр класса
class myClass {
public void Method2() {
synchronized(someOtherObj) {
/* some code */
}
}
public synchronized void Method3() {
/* some code without synchronized blocks */
}
public void Method4() {
/* some code without synchronized blocks */
}
}
Помогите мне понять, какие кодовые блоки myobject доступны только для протектора, называемого методом Method1.
Есть два способа синхронизации чего-то. Синхронизировать метод можно:
public synchronized void doSomething() {
// safe to do stuff
}
или вы можете синхронизировать объект:
synchronize( object ) {
// safe to do stuff
}
В вашем примере Class1.Method1 и myClass.Method3 и myClass.Method4 будут блокировать друг друга. myClass.Method2 блокирует someOtherObject, который не влияет ни на что в этом примере.
Что может быть неприятным, когда вы добавляете синхронизированное ключевое слово к методу, это действительно просто блокировка этой "ссылки".
public synchronized void method() { }
такой же как:
public void method() {
synchronized( this ) {
// this may help clarify
}
}
Это все, что вы получаете. Когда объект синхронизируется, к ним не могут обращаться никакие другие объекты в других потоках. Это может быть трудно получить. Я рекомендую следующую книгу:
Java-параллелизм на практике Брайана Гетца и др. Ссылка: http://amzn.com/0321349601
Вы должны знать, что
void synchronized myfunc()
коротко для:
void myfunc() {
synchronized (this) {
}
}
где this
текущий экземпляр класса, вызываемого извне.
Поэтому, если у вас есть следующая настройка:
final MyClass a = new MyClass();
// Thread 1:
a.myfunc();
// Thread 2:
a.myfunc();
Тогда оба потока будут ждать на одном и том же объекте (который является экземпляром a).
Однако в следующей настройке:
final MyClass a = new MyClass();
final MyClass b = new MyClass();
// Thread 1:
a.myfunc();
// Thread 2:
b.myfunc();
Оба потока могут одновременно получать доступ к myfunc
, потому что они синхронизируются на разных объектах (экземпляр a для потока 1 и экземпляр b для потока 2).
Если вы напишете код следующим образом:
final Object a = new Object();
final Object b = new Object();
static void myfunc() {}
// Thread 1:
synchronized(a) {
myfunc();
}
// Thread 2:
synchronized(b) {
myfunc();
}
Это было бы то же самое (с учетом блокировки), потому что, как указано выше, синхронизированный метод - это просто короткое выражение для synchronized(this)
.
Помогите мне понять, какие кодовые блоки myobject доступны только для протектора, называемого методом Method1.
Я думаю, что у вас есть синхронизация назад. Ни один другой поток не может выполнять блок внутри Class1#Method1()
если он не удерживает "блокировку" myobject
. Фактические методы myClass
не затронуты. Любые методы из любых потоков могут ссылаться на методы myobject
если они имеют ссылку на него. (Так как методы в myClass
также синхронизированы, они также могут блокироваться, но это отдельная проблема.)
По этой причине важно всегда блокировать объект, который вы блокируете, а не публиковать ссылку, возвращая его в любом общедоступном методе.