2013-08-01 4 views
0

Я хочу знать, эквивалентны ли эти два сценария или нет в многопоточной среде.Явская эквивалентность внутренней и явной глобальной блокировки

private final Lock globalLock = new ReentrantLock(); 

Сценарий 1

public void addListener(Listener listener) { 
    globalLock.lock(); 
    try{ 
    //blah blah 
    }finally { 
     globalLock.unlock(); 
    } 
} 

public void removeListener(Listener listener) { 
    globalLock.lock(); 
    try{ 
    //blah blah 
    }finally { 
     globalLock.unlock(); 
    } 
} 

Сценарий 2

public synchronized addListener(Listener listener) { 
} 

public synchronized removeListener(Listener listener) { 
} 

Я думаю, что первый сценарий имеет условия гонки в многопоточной среде, потому что если тема А вызывает метод добавления слушателя() перед тем тему B вызывает removeListener(), все еще существует вероятность того, что Thread B получит блокировку до Thread A, хотя Thread Invo ked addListener() до того, как Thread B вызывается removeListener(). Является ли эта гипотеза правильной или Java гарантирует, что по крайней мере один оператор метода будет выполнен до того, как Thread будет запланирован.

+0

Да, globalLock - глобальное конечное поле –

+0

Ситуация, о которой вы описали, не является условием гонки. Вызовы addListener и removeListener из разных потоков не могут рассматриваться в терминах «раньше» или «после». –

ответ

1

Они функционально эквивалентны (предполагается, что globalLock является переменной конечного экземпляра).

В первом примере, если два потока одновременно вызовут два метода, только один из них сможет получить блокировку, а второй должен будет дождаться, пока первый из них освободит блокировку.

+0

Да, я это понимаю. Мой вопрос в том, что если два потока вызывают методы независимо BUT Thread A вызывает перед Thread B, может ли Thread B получить блокировку перед потоком A? Фактически я хочу знать, вызывается ли данный addlistener() перед RemoveListener() отдельными потоками, эта реализация обеспечивает гарантию заказа программы? –

+0

Не уверен, что я понимаю: либо вы используете синхронизацию, чтобы гарантировать, что Thread A вызывает метод до Thread B, и это то, что произойдет, или вы этого не сделаете, и это будет случайным. То же самое относится к синхронизированным методам. – assylias

1

Непонятно, какой глобальный замок. Если это поле экземпляра

private final Lock globalLock = new ReentrantLock(); 

public void addListener(Listener listener) { 
    globalLock.lock(); 
    ... 

то ответ да, эти два сценария эквивалентны

+0

см. Мой комментарий к assylias –

0

Они не точно эквивалентны в многопоточной среде. Да функционально они такие же, как предложено assylias.

Но их большая разница между двумя подходами. Эта большая разница в том, что в сценарии 1 ваш заблокирован. и, следовательно, это хорошая практика, потому что уверен, что никто другой не может владеть вашим замком. Хотя сценарий не очень хороший подход (за исключением некоторых случаев), потому что любой другой пользователь может удерживать блокировку больше, так как теперь ваш замок является общедоступным.

Так функционально эквивалентны, но по дизайну они разные.

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