Что в действительности блокирует Java-синхронизированный (Object obj)?

1

Предположим, что мы имеем следующий класс

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.

  • 0
    не могли бы вы перефразировать.
  • 0
    Это невозможно. Но вы можете заблокировать доступ к своему классу, добавив специальную проверку ко всем методам вашего класса.
Показать ещё 2 комментария
Теги:
multithreading
synchronization

3 ответа

1
Лучший ответ

Есть два способа синхронизации чего-то. Синхронизировать метод можно:

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

0

Вы должны знать, что

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).

0

Помогите мне понять, какие кодовые блоки myobject доступны только для протектора, называемого методом Method1.

Я думаю, что у вас есть синхронизация назад. Ни один другой поток не может выполнять блок внутри Class1#Method1() если он не удерживает "блокировку" myobject. Фактические методы myClass не затронуты. Любые методы из любых потоков могут ссылаться на методы myobject если они имеют ссылку на него. (Так как методы в myClass также синхронизированы, они также могут блокироваться, но это отдельная проблема.)

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

  • 0
    Вы правы, у меня нет понимания синхронизации. Но я стараюсь справиться с этим.
  • 0
    Зачем тогда нужно ставить какой-либо объект как «замок»? Что изменится, если я использую какой-то другой объект, например синхронизированный (это).
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню