Как реализовать спин-блокировку, чтобы избежать блокировки

Рассмотрим следующий код:

// Below block executed by thread t1
synchronized(obj) {
   obj.wait(0);
}

// This block executed by thread t2
synchronized(obj) {
    obj.notify();
}

Я понимаю, что в приведенном выше коде, если t1 стал владельцем синхронизированного блока, и в то же время, если поток t2 пытается взять синхронизированный блок, то t2 переходит на ожидание ядра. Я хочу избежать этой ситуации и вращать t2 перед блоком, пока t1 не вызовет ожидание и не оставит право собственности на блок. Это возможно?


person Kiran Prabhu    schedule 03.11.2014    source источник
comment
Пожалуйста, приложите больше усилий для форматирования вашего сообщения, прежде чем нажимать «Отправить» — используйте предварительный просмотр, чтобы увидеть, как будет выглядеть сообщение, и отправьте его только тогда, когда оно выглядит так, как вы хотели бы, чтобы оно выглядело, если бы вы отвечали. вопрос.   -  person Jon Skeet    schedule 03.11.2014
comment
Кроме того, есть ли у вас доказательства того, что это действительно вызывает проблему в вашем коде? Спин-блокировка очень редко является правильным решением - и имейте в виду, что t1 откажется от блокировки, как только вызовет wait(), поэтому окно возможностей для блокировки t2 действительно очень мало.   -  person Jon Skeet    schedule 03.11.2014
comment
Почему вы хотите это сделать? Вместо того, чтобы один поток ожидал блокировки, у вас был бы один поток, ожидающий блокировки, и в то же время тративший впустую циклы ЦП.   -  person Thomas Stets    schedule 03.11.2014
comment
мое использование этого блока кода слишком болтливо, несколько потоков ждут и уведомляют, я не хочу, чтобы мой поток переходил в ожидание ядра, скорее я могу немного покрутиться и получить право собственности   -  person Kiran Prabhu    schedule 03.11.2014
comment
Согласитесь, что ОП должен расширять почему, но если бы никогда не было хорошей потребности, то пакет java.util.concurrent.locks не был бы создан.   -  person Erwin Bolwidt    schedule 03.11.2014
comment
@ThomasStets, вероятно, из-за карго-культа «блокирующий плохое, неблокирующее хорошее».   -  person Martin James    schedule 03.11.2014
comment
@Erwin, этот пакет был создан для совершенно других целей, чем для контроля того, будет ли и как долго вращаться блокировка перед вызовом ядра (где он вообще это позволяет? Никогда не сталкивался с этим). По действительно веским причинам - это деталь реализации, с которой JVM может справиться сама по себе.   -  person Voo    schedule 03.11.2014


Ответы (4)


JVM не нужно реализовывать вход в заблокированный синхронизированный блок как жесткий блок и переключение контекста. У него есть возможность использовать более легкие методы, такие как спин-блокировки. На самом деле, Oracle JVM идет на несколько длин, чтобы избежать блокировки. Таким образом, вы можете обнаружить, что JVM уже выполнила эту оптимизацию за вас. А если нет, то это может быть связано с тем, что у JVM есть доказательства того, что спин-блокировка — плохая идея.

person Raedwald    schedule 03.11.2014
comment
Спасибо, Редвальд. Не могли бы вы поделиться какими-либо ссылками, которые предполагают это. - person Kiran Prabhu; 04.11.2014

Да, можно делать что хочешь.

Реализация интерфейса java.util.concurrent.locks.Lock (например, ReentrantLock) позволяет вам ждать блокировки с помощью метода tryLock (вызывается из цикла).

Чтобы реализовать функции wait и notify, вы вызываете метод newCondition для Lock, чтобы получить объект Condition. Интерфейс Condition имеет методы await и signal/signalAll, которые работают аналогично wait и notify/notifyAll.

person Erwin Bolwidt    schedule 03.11.2014

Очень легко реализовать спин-блокировку в Java. Идея состоит в том, чтобы воспользоваться преимуществами метода tryLock() интерфейса Lock.

 import java.util.concurrent.locks.ReentrantLock;

public class SpinLock extends ReentrantLock{

public SpinLock() {
  super();
 }


 public void lock() {
  while(!super.tryLock()) {
    // Do Nothing
  }

 }

 public void unlock() {
  super.unlock();
 }

}

Ссылка: https://tech693.blogspot.com/2018/08/java-spin-lock-implementation.html

person Java Guru    schedule 02.09.2018

person    schedule
comment
Нет необходимости в CAS для реализации SpinLock. Изменение цикла на что-то вроде while (getAndSet(true) == true), вероятно, будет полагаться на более легкую инструкцию xchg. Но это еще не все, и, вероятно, лучше полагаться на JVM, чтобы делать то, что правильно. - person MappaM; 07.11.2018