Обмен технологиями

Язык Go — параллельный канал программирования (двухканальный, одноканальный) и примеры приложений (производитель-потребитель, модель принтера).

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Канал

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

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

тип канала

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

make (chan Type)
make (chan Type,capacity)
  • 1
  • 2
  • Когда емкость=0, канал не буферизуется и блокирует чтение и запись. Когда емкость>0, канал имеет кэш и не блокируется. Запись не будет блокироваться до тех пор, пока элементы емкости не будут заполнены.
  • Chamnel получает и отправляет данные через оператор <-. Синтаксис отправки и получения данных:
channel<-value   //发送value 到channel
<-channel     //接收并将其丢弃
x:=<-channel   //从 channel 中接收数据,并賦偵给x
x,ok:=<-channel   //功能同上,同时检查通道是否已关闭或者是否为空
  • 1
  • 2
  • 3
  • 4

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

выполнить

Вставьте сюда описание изображения

  • Трубы размещаются одна перед печатью, а другая сзади.
  • Если Person2 выполняется первым и в конвейере нет данных, он будет заблокирован.
  • Person1 выполнит, и после печати данных введите данные в канал Person2, распознает их и начнет печать.

Реализуйте синхронизацию и взаимодействие данных по каналам

Вставьте сюда описание изображения
Вставьте сюда описание изображения

небуферизованный канал

Небуферизованный канал — это канал, который не имеет возможности сохранять какое-либо значение перед приемом.
Этот тип канала требует, чтобы горутина отправки и горутина получения были готовы одновременно завершить операции отправки и получения. Если две горутины не готовы одновременно, канал приведет к тому, что горутина, которая первой выполняет операцию отправки или получения, заблокируется и будет ждать.
Это взаимодействие отправки и получения в канале по своей сути синхронно. Ни одна операция не может существовать независимо от другой.
На следующем рисунке показано, как две горутины могут совместно использовать значение, используя небуферизованные каналы:
Вставьте сюда описание изображения

  • То есть сам канал не может хранить вещи. Если вы что-то в него положите, вы можете это сразу вынуть.
  • На шаге 1 обе горутины прибывают на канал, но ни одна из них не начинает ни отправлять, ни получать.
  • На шаге 2 горутина слева проникает в канал, что имитирует процесс отправки данных в канал. В это время горутина будет заблокирована в канале до завершения обмена.
  • На шаге 3 горутина справа засовывает руку в канал, что имитирует получение данных из канала. Эта горутина также будет заблокирована в канале до завершения обмена.
  • На шагах 4 и 5 происходит обмен и, наконец, на шаге 6 обе горутины вынимают руки из канала, что имитирует освобождение заблокированной горутины. Обе горутины теперь могут делать другие вещи.

Создать небуферизованный канал

make (chan Type)//等价于make (chan Type,0)
  • 1

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

Вставьте сюда описание изображения

  • ch&lt;-i записывает данные в канал. Основная сопрограмма не будет выполняться, пока не обнаружит это. В это время подпрограмма также заблокируется и будет ждать. После того, как канал прочитает данные, подпрограмма продолжит работу.
  • Однако println печатает данные после чтения канала, поэтому скорость печати определяется системой.

буферизованный канал

Буферизованный канал — это канал, который может хранить одно или несколько значений перед их получением.
Этот тип канала не требует, чтобы горутина выполняла отправку и получение одновременно. Каналы также будут иметь разные условия, которые блокируют действия отправки и получения. Действие приема будет заблокировано только в том случае, если в канале для приема нет значения. Действие отправки будет заблокировано только в том случае, если в канале нет доступного буфера для размещения отправляемого значения.
Это приводит к большой разнице между буферизованными и небуферизованными каналами: небуферизованные каналы гарантируют, что отправляющие и получающие горутины будут обмениваться данными одновременно: буферизованные каналы не имеют такой гарантии.
Вставьте сюда описание изображения

  • На шаге 1 горутина справа получает значение из канала.
  • На шаге 2 горутина справа самостоятельно завершает действие по получению значения, а горутина слева отправляет новое значение в канал.
  • На шаге 3 горутина слева все еще отправляет новое значение в канал, а горутина справа получает другое значение из канала. Две операции на этом этапе не синхронизируются и не блокируют друг друга.
  • Наконец, на шаге 4 все отправка и получение завершены, и в канале еще есть несколько значений и некоторое пространство для хранения дополнительных значений.

создавать

make (chan Type,capacity)
  • 1

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

выполнить

Вставьте сюда описание изображения

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

закрыть канал

Канал может использовать ok, чтобы определить, открыт ли канал. Если канал закрыт, данные не будут считаны.

Вставьте сюда описание изображения

  • num ,ok:=<-chМожет определить, закрыт ли канал.

Уведомление

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

Односторонний канал

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

var ch1 chan int //ch1双向
var ch2 chan<-float64 //ch2单向,只能用于写float64数据
var ch3 <-chan int  //ch3单向,只能用于读int数据
  • 1
  • 2
  • 3

chan&lt;- означает, что данные поступают в канал, и данные записываются в канал, который выводится вызывающей стороне.
&lt;-chan указывает, что данные выходят из канала. Для вызывающей стороны данные получаются из канала, что, конечно же, является входными данными.
Канал можно неявно преобразовать в одностороннюю очередь, только получая или только отправляя, но односторонний канал нельзя преобразовать в обычный канал;

Вставьте сюда описание изображения

Используйте один канал для реализации модели производитель-потребитель.

Вставьте сюда описание изображения