Блокировать без вращения в Java? - PullRequest
4 голосов
/ 09 января 2009

Некоторые методы в Java будут блокироваться до тех пор, пока они не смогут что-то сделать, например ServerSocket.accept () и InputStream.read (), но как это сделать, мне нелегко найти. Самое близкое, что я могу вспомнить, это цикл while () с Thread.sleep () каждый раз, но чем дольше период ожидания, тем менее отзывчивым является блокировка и чем короче сон, тем больше происходит вращение.

У меня два вопроса:

  1. Как блокируются различные стандартные функции, такие как приведенные выше? Родной код? циклы while ()? Что-то другое?

  2. Как мне реализовать методы, которые блокируют?

Ответы [ 4 ]

10 голосов
/ 09 января 2009

Операции, которые вы перечислили, блокируются из-за базовой платформы (т. Е. Собственного кода).

Вы можете реализовать блок, используя методы Java Object.wait() и Object.notify(); wait() будет блокировать вызывающий поток, пока другой поток не вызовет notify() для той же блокировки.

6 голосов
/ 09 января 2009

Основной ответ на (1) - «не беспокойся об этом - операционная система справится с этим». Вызовы, такие как чтение из входных потоков, по сути являются обертками для вызовов операционной системы. Под капотом внутри ОС, как мне кажется, обычно происходит, когда вызов «блокирует» в этих случаях то, что ОС «знает», что она ожидает аппаратного прерывания, скажем, от контроллера диска, чтобы сказать, что такой-и - такие запрошенные данные теперь доступны, и он знает, что поток X запросил эти данные. Таким образом, он не планирует снова в потоке X, пока не получит это прерывание (или прерывание, говорящее «произошла ошибка» и т. Д.). (И часть алгоритма планирования потока затем делает такие вещи, как предоставление ожидающему потоку временного «повышения» некоторого вида, когда эти ожидаемые данные становятся доступными. Опять же, обычно вам не нужно слишком беспокоиться об этом.) Или другими словами: какими бы точными ни были детали этого механизма, он недоступен обычному программисту на Java.

В (2) я бы предложил больше подумать о том, «как мне сделать Вещи X, которые могут оказаться блокированными». Я думаю, что ответ вряд ли когда-либо заключается в том, что Thing You Want To Do намеренно является просто «блоком», и чем бы Thing X ни был, вероятно, есть библиотечный метод / класс, который сделает это за вас. Например (ссылки включают некоторые материалы, которые я написал на эти темы):

  • если вы хотите получить следующее сообщение / задание, когда оно станет доступным из какой-либо очереди / провайдера, посмотрите блокирующие очереди
  • если вам нужно контролировать доступ к общему ресурсу с помощью «блокировки» на объекте, ожидая, когда блокировка станет доступной, если необходимо, рассмотрите простую старую синхронизацию или явную блокировку ;
  • если вы хотите подождать, пока один из множества объединенных ресурсов станет доступным, посмотрите на семафоры

Я бы сказал, что необработанный механизм ожидания / уведомления в значительной степени устарел с API параллелизма Java 5. И что бы вы ни делали, спинлокинг обычно является самым последним средством.

4 голосов
/ 09 января 2009

Чтобы ответить (2), вы хотите, чтобы методы Object ожидали, уведомляли и уведомляли все.

При использовании Object.wait () вы должны заключить ожидание в цикл, который проверяет условие, на котором вы ожидаете. Метод wait () может возвращаться ложно (по незаметным причинам).

Кроме того, вам необходимо учитывать, нужно ли вам использовать notify () или notifyAll () - если все ожидающие потоки ожидают абсолютно одинакового условия и вам нужен только один для обработки того, о чем вы уведомляете для, вы можете использовать notify (), в противном случае вам нужно использовать notifyAll (), так как у вас нет гарантии, какой поток будет уведомлен о notify () - вы, например, не можете ожидать, что они будут циклически разбиты.

Наконец, убедитесь, что вы посмотрите на пакет java.util.concurrent - он имеет много более высокого уровня и лучших решений для общих проблем с потоками, чем примитивы Java.

2 голосов
/ 09 января 2009

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

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

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