Блокировки, полученные на экземплярах в многопоточности Java - PullRequest
0 голосов
/ 21 февраля 2011

Я читал, что блокировки в Java получены на основе экземпляра (объекта) (в случае метод экземпляра )
Также блокировки могут быть получены на объекте класса (в случае статический метод ).

Но мне было интересно сколько блокировок можно получить одновременно конкретным объектом ?

Может ли объект обладать более чем одним замком одновременно?
Если да, пожалуйста, объясните на примере.

Пожалуйста, помогите мне прояснить мою концепцию.

Ответы [ 5 ]

2 голосов
/ 21 февраля 2011

Только на один объект на синхронизированный блок.Объекты не будут обладать замками.Это поток выполнения, который блокирует объект для работы с ним.

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

Object obj = new Object();

synchronized(obj) {
    workOnIt(obj);
}

Второй выглядит так, как будто он блокирует класс.Но Test.class - это специальное представление для экземпляра java.lang.Class моего класса Test.

synchronized(Test.class) {
    // call some static method here
}
1 голос
/ 21 февраля 2011

Один поток может содержать несколько блокировок для нескольких объектов.Но вы должны идти на свой риск (чтобы избежать блокировки или снижения производительности)

synchronized (obj1)
{
  synchronized (obj2)
  {
    // do sth. against obj1 and obj2 
  }
}
0 голосов
/ 21 февраля 2011

Когда вы получаете блокировку для класса статическим методом, вы получаете блокировку для объекта, как и для любого другого.

class A {
    synchronized void foo() { 
        // do something.
    }

    static synchronized void bar() { 
        // do something.
    }
}

в основном совпадает с

class A {
    void foo() { 
        Object locked = this;
        synchronized(locked) {
            // do something.
        }
    }

    static void bar() { 
        Object locked = A.this;
        synchronized(locked) {
            // do something.
        }
    }
}

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

Lock lock = new ReentrantLock();
lock.lock();
lock.unlock();

однако, вы можете сбить с толку

Lock lock = new ReentrantLock();
synchronized(lock) { // don't do this.
   lock.wait(); // argh.
}
0 голосов
/ 21 февраля 2011

Рассмотрим метод с синхронизированным блоком (адаптировано из JVMS )

public void foo(Object f) {
  synchronized(f) {
    doSomething();
  }
}

Давайте переведем его на псевдокод (смесь Java и байт-кода !!!):

public void foo(Object f) {
  monitorenter(f);
  try {
    doSomething();
    monitorexit(f);
  } catch(Throwable e) {
    monitorexit(f);
    throw e;
  }
}

Вот так это будет выглядеть, , если инструкция байт-кода monitorenter и monitorexit были бы методами java.

Каждый объект имеет один монитор. Если один поток входит в монитор и монитор не получен (заблокирован, получен), то он получает (блокирует, получает) монитор и вызывает doSomething() (который является следующей строкой).

Если теперь появляется второй поток и пытается войти в монитор объекта f, то он ждет в этом месте, пока монитор объекта f не будет освобожден. Монитор освобождается, когда первый поток вызывает одну из двух monitorexit инструкций (байт-код !!).

Вернуться к вопросу - сколько мониторов может быть введено одним потоком? Не может быть никаких ограничений (кроме ограничений размера стека). Если doSomething является другим синхронизированным методом и использует монитор объекта g, то поток 1 также войдет в этот монитор и получит монитор на g (если доступно).

Это , а не объект, который получает блокировку, это поток , который входит в монитор объектов, и этот процесс "блокируется".

0 голосов
/ 21 февраля 2011

Блокировка (в форме синхронизированного блока или метода) имеет один основной эффект: только один поток одновременно может вводить синхронизированный блок / метод этого объекта, т.е. только один поток может быть владельцем этой блокировки.(или «монитор», как его называют в JLS).

(Другой эффект заключается в том, что все переменные, измененные внутри (или до) одного синхронизированного блока, гарантированно будут видны в других потоках, когда они находятся вили после) более поздний синхронизированный блок на том же мониторе.)

Сколько объектов / переменных вы используете в этом блоке, это ваше свободное решение, но обычно вы используете одну блокировку для всех данных, которые каким-то образом находятся вместе,и не должны быть изменены / доступны независимо.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...