2012-03-30 2 views
1

С точки зрения перспективы, что такое блок, ждать и блокировать? Скорее, нужно ли иметь все эти три в любой операции? Например, в шаблоне производителя-потребителя, как это реализовано. Заранее спасибоПоведение темы

ответ

2

A Операция блокировки - это та, которая блокирует поток до завершения операции. Блокировка поток - это процесс передачи планировщику потоков (обычно это операционная система, хотя есть библиотеки потоков пользовательского уровня), чтобы не запускать поток до тех пор, пока этот поток не проснется. Существует множество видов операций блокировки, и одним из примеров является ввод/вывод файлов. Как и в случае любой другой операции блокировки, метод не возвращается до завершения соответствующей операции (в этом случае ввода-вывода файла).

A wait - особый вид операции блокировки, используемой для синхронизации потоков. В частности, он говорит: «Пожалуйста, заблокируйте поток, который называется wait, пока какой-то другой поток не просыпается». В Java, подождите method. Соответствующий способ пробуждения - notify.

A lock - это абстракция более высокого уровня, в которой говорится: «Разрешить ограниченное количество потоков в эту область кода». Чаще всего это ограниченное число равно 1, и в этом случае мьютексом (который я подробно объясняю в this SO answer) является предпочтительным фиксирующим примитивом на языке более низкого уровня, например C. В Java наиболее распространенный фиксирующий примитив называется монитор. Существует понятие владения монитором объекта (каждый объект имеет монитор) и ожидание на мониторе, а также пробуждение потока, ожидающего на мониторе. Как это сделать? Вы уже догадались - мы используем метод wait для ожидания на мониторе и notify, чтобы разбудить один из потоков, ожидающих на мониторе.

Теперь ответ, который, вероятно, будет звучать как греческий, учитывая, что вы только начинаете с параллелизма: для реализации шаблона производителя-потребителя наиболее распространенной стратегией является использование двух семафоров (плюс мьютекс для синхронизации доступа к буфер). Семафор обычно реализуется с помощью мьютекса, но является конструкцией более высокого порядка, потому что он позволяет подсчитать некоторый ресурс. Таким образом, вы сохраняете один семафор для подсчета количества элементов в буфере и подсчета количества пустых пробелов в буфере. Производитель ожидает пустой семафор пространства и добавляет элементы в буфер, когда пространство становится доступным, и потребитель ждет семафора элементов и потребляет элемент всякий раз, когда предмет становится доступным.

Теперь я определил, что это за вещи, но я действительно не говорил о том, как использовать. Это, однако, стоит нескольких лекций в колледже, и, безусловно, слишком много для ответа StackOverflow. Я бы рекомендовал уроки параллелизма в the Java tutorials, чтобы начать работу с потоками. Кроме того, посмотрите учебные курсы в Интернете. Многие школы публикуют заметки в Интернете, поэтому при небольшом поиске вы часто можете найти высококачественный материал.


EDIT: Описание разницы между ожиданием и блокировки ввода/вывода

Перед тем, как начать читать это, убедитесь, что вы знакомы с тем, что нить есть, и то, что процесс , Я даю объяснение в первых четырех параграфах this SO answer, а Wikipedia имеет более подробное объяснение (хотя и с менее историческим контекстом).

Каждый поток имеет одну очень важную информацию: указатель инструкции (есть и другие важные части информации, связанные с каждой нитью, но они не важны сейчас). Указатель инструкций является поддерживаемым JVM указателем на исполняемую команду байт-кода. Каждый раз, когда вы выполняете инструкцию (каждая инструкция представляет собой абстрактное представление очень простой операции, например «метод вызова foo на объекте x), указатель инструкции перемещается вперед к некоторой« следующей инструкции ». Для запуска вашей программы JVM устанавливает указатель команд на начало main и продолжает выполнять инструкции и перемещение указателя команд вперед, пока программа не выходит как-то.

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

Теперь существует множество различных операций блокировки. Один из них блокирует ввод-вывод. Если вы вызываете System.out.println, например, метод println не возвращается, пока текст не будет выписан на консоль. В этом случае указатель инструкций останавливается где-то внутри System.out.println, а операционная система сигнализирует о том, что поток просыпается всякий раз, когда заканчивается консольная печать. Таким образом, нить не должна начинать свой собственный указатель инструкции, перемещаясь снова, но метод все равно возвращается сразу после того, как текст будет записан на консоль. Таким образом, на очень высоком уровне:

  • Thread 0 звонки System.out.println("foo")
  • темы указатель команды 0 останавливает перемещение в то время как операционная система записывает «Foo» в консоли
  • Когда операционная система выполняется письменно в console, он уведомляет JVM, и JVM автоматически начинает перемещать указатель инструкции потока 0. Все это происходит без программиста, который пишет об этом System.out.println.

Другого совершенно отдельный вида блокирующей операции инкапсулируется в методе Object.wait.Всякий раз, когда поток вызывает Object.wait, указатель инструкции этого потока прекращает движение, но вместо того, чтобы операционная система снова начала перемещение указателя команды, другой поток выполняет эту работу. В этом случае нет внешнего события, которое вызовет перезапуск указателя инструкции потока (как в случае блокирующего ввода-вывода), но там - событие, внутреннее для программы. Как я уже сказал, другой поток запустит указатель инструкции, перемещаясь снова, вызвав Object.notify. Таким образом, на очень высоком уровне:

  • Thread 0 звонки x.wait() на какой-либо объект
  • указатель команд Поток 0 останавливает перемещение
  • тему 1 вызывает x.notify() на одном объекте x
  • Поток 0 начинается указатель инструкция двигаться снова
  • Thread 0 и 1 нить теперь выполняются параллельно

Обратите внимание, что гораздо больше работы должно идти в письменной форме ожидания/уведомления правильно - JVM и операционная система не выполняют всю работу для вас на этот раз. Они по-прежнему фактически выполняют большую часть работы для вас, но вам действительно нужно подумать о вызове wait и notify и о том, как они позволяют вам общаться между потоками, реализовывать блокировки и т. Д.

Так что в этой истории есть две морали. Во-первых, блокирование ввода-вывода и wait - совершенно разные звери. В обоих случаях поток блокируется, но в случае блокирующего ввода-вывода поток автоматически запускается операционной системой, а в случае wait поток должен полагаться на другой поток, вызывающий notify, чтобы разбудить его. Во-вторых, параллельное программирование сложнее рассуждать, чем серийное программирование. Примеры игрушек, которые я поставил в этом ответе, на самом деле не делают второй вопрос справедливости.

+0

В соответствии с вами, wait(), notify() должны использоваться. Таким образом, эти операции блокируют ввод, правильно? поэтому мы можем сказать, что когда мы используем wait(), неявно, происходит блокирование IO ... – UVM

+0

@UNNI Нет, это не тот случай. Операция блокировки - это операция, которая останавливает поток от выполнения в течение некоторого времени, а вход - * один вид * операции блокировки, в то время как ожидание - это другой вид операции блокировки. Я обновил свой ответ, чтобы отразить это. –

+0

, из вашего ответа операция ожидания используется \ n для синхронизации потоков, а также блокирует IO.So в основном, когда мы используем метод wait() в программе, эти вышеупомянутые сценарии выполняются неявно, не так ли? – UVM

0

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

Вот хорошее объяснение с примером модели производителя потребительских:

http://www.ase.md/~aursu/JavaThreadsSynchronization.html

Ура!

+0

Эта ссылка показывает использование потребителя-производителя двумя способами. Один использует метод yield(), а другой использует обычный режим ожидания и уведомляет. Но на самом деле первый метод не является стандартным решением, в котором вышеупомянутые параметры используются.подробнее см. эту ссылку.http: //www.javamex.com/tutorials/threads/yield.shtml. А также, если есть операция lock(), все равно можно использовать yeild. (Потому что это не будет изменить право собственности). – UVM

0

Блок: Предотвращение выполнения.
Ждать: Подвешивает текущую резьбу.
Lock: Когда вы блокируете его, другие не могут использовать его.
Рассмотрите возможность покупки в Интернете, когда клиент покупает видеоролик Как только он выбирает место. Другие не смогут получить это место одновременно (блокировка этих мест).

+0

PLS понять мой вопрос – UVM

+0

Это зависит от вашего требования, если вы знаете о системе, вы можете решить, идти ли с нитью или нет. Лучше вы расширяете свой сценарий, чтобы получить лучший результат. – special