2015-11-20 2 views
1

У меня есть ситуация, и мне нужен совет о блоке synchronized на Java. У меня есть тестовый класс ниже:Как работает синхронизированный блок в Java? Переменная ссылка или память заблокированы?

Class Test{ 
    private A a; 
    public void doSomething1(String input){ 
     synchronized (a) { 
      result = a.process(input); 
     } 
    } 
    public void doSomething2(String input){ 
     synchronized (a) { 
      result = a.process(input); 
     } 
    } 
    public void doSomething3(String input){ 
      result = a.process(input); 
    } 
} 

То, что я хочу, когда мульти потока вызывают методы doSomeThing1() или doSomeThing2(), объект «а» будет использоваться и разделяемые между несколькими потоками (это должно быть) и обрабатывает только один ввод в то время (ожидая, пока другие потоки установят объект «a» бесплатно), и когда вызывается doSomeThing3, вход обрабатывается немедленно.

Мой вопрос будет касаться метода doSomeThing3() моего метода doSomeThing1() и doSomeThing2()? Нужно ли ждать, если doSomeThing1() и doSomeThing2() используют объект "a"?

ответ

0

В вашем коде doSomething3() может продолжаться параллельно с doSomething1() или doSomething2(), поэтому в этом смысле он делает то, что вы хотите. Однако, в зависимости от того, что делает a.process(), это может привести к состоянию гонки и повреждению данных. Обратите внимание, что даже если doSomething3() вызывается, все вызовы doSomething1() или doSomething2(), которые были запущены, будут продолжены; они не будут отменены, а doSomething3() обработано.

+0

Все методы используют одно и то же соединение в боковом объекте 'a'. DoSomething1() и doSomething2() отвечают за обработку какой-либо транзакции, которая не может быть выполнена в многопоточной среде, поэтому они (отдельные) не могут быть выполнены одновременно с тем же запросом. Если doSomething1() использует объект a, другие doSomething1() должны ждать (приведет к отключению блокировки или занятости). DoSomething3() предназначен для других типов данных. Еще одна вещь, на которую вы могли бы помочь мне ответить - будет doSomething2() работать параллельно с doSomething1()? –

+0

Синхронизированные части doSomething1() и doSomething2() не будут работать параллельно. –

+0

@LinhNguyen Целесообразно использовать несколько выделенных объектов блокировки для независимых операций. Таким образом, эти независимые операции могут выполняться параллельно, а также намерение лучше документировано. Конечно, эти независимые операции не должны передавать изменчивые данные. –

4

A метод никогда не подвергается воздействию ничего, что и ваши темы. На что влияет данные, и ответ на ваш вопрос полностью зависит от того, какие данные обновляются (если есть) внутри вызова a.process().

Вы спрашивали: «Переменная ссылка или память заблокирована?»

Прежде всего, «переменная» и «память» - это одно и то же. Переменные, а также поля и объекты - это абстракции более высокого уровня, которые построены поверх идеи более низкого уровня «памяти».

Во-вторых, нет. Блокировка объекта не препятствует доступу других объектов или изменению объекта, а также от доступа или изменения чего-либо еще.

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

Что это означает для вашего примера, если поток X вызывает doSomething1() и изменяет объект a; а затем поток Y позже вызывает doSomething3(), поток Y - , а не, гарантированно увидит обновления. Он может видеть объект в его исходном состоянии, он может видеть его в полностью обновленном состоянии или может видеть его в некотором недопустимом состоянии на полпути. Причина в том, что, хотя поток X заблокировал объект, изменил его, а затем отпустил блокировку; нить Y никогда не блокирует тот же объект.

+0

large: Метод процесса ничего не обновляет внутри объекта 'a'. Цель, которую я использую синхронизированный блок, - это не то, что два метода doSomeThing1() или doSomeThing2() выполняются одновременно. Это может привести к тому, что моя программа будет занята. Меня интересует производительность каждого метода doSomething(). Не могли бы вы рассказать мне об этом? –

+0

Я спрашиваю о переменной производительности и памяти, потому что я хочу знать, что есть какие-то различия, если я использую приведенный ниже код doSomething1 (String input) {A b = a; синхронизированный (b) { результат = b.процесс (ввод); } } –

Смежные вопросы