Berbagi teknologi

Bahasa Go --- saluran pemrograman bersamaan (saluran ganda, saluran tunggal) dan contoh aplikasi (konsumen produsen, model printer)

2024-07-12

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

Saluran

Goroutine berjalan di ruang alamat yang sama, jadi akses ke memori bersama harus disinkronkan.Goroutine berbagi memori melalui komunikasi, bukan berbagi memori.

Saluran tipe referensi adalah implementasi spesifik dari mode CSP dan digunakan untuk komunikasi beberapa goroutine. Ini menerapkan sinkronisasi secara internal untuk memastikan keamanan konkurensi.

jenis saluran

Seperti peta, saluran juga merupakan referensi ke struktur data dasar yang dibuat oleh make.
Saat kita menyalin saluran atau menggunakannya untuk meneruskan parameter fungsi, kita hanya menyalin referensi saluran, sehingga pemanggil dan penerima panggilan akan mereferensikan objek saluran yang sama. Seperti tipe referensi lainnya, nilai nol saluran adalah nihil.
Saat Anda menentukan saluran, Anda juga perlu menentukan jenis nilai yang dikirim ke saluran tersebut. Saluran dapat dibuat menggunakan fungsi make() bawaan:

make (chan Type)
make (chan Type,capacity)
  • 1
  • 2
  • Ketika kapasitas=0, saluran tidak di-buffer dan memblokir pembacaan dan penulisan. Ketika kapasitas>0, saluran memiliki cache dan non-pemblokiran. Penulisan tidak akan diblokir sampai elemen kapasitas terisi.
  • Channel menerima dan mengirimkan data melalui operator <-. Sintaks untuk mengirim dan menerima data adalah:
channel<-value   //发送value 到channel
<-channel     //接收并将其丢弃
x:=<-channel   //从 channel 中接收数据,并賦偵给x
x,ok:=<-channel   //功能同上,同时检查通道是否已关闭或者是否为空
  • 1
  • 2
  • 3
  • 4

Secara default, saluran memblokir saat menerima dan mengirim data, kecuali ujung lainnya sudah siap, membuat sinkronisasi goroutine menjadi lebih sederhana tanpa memerlukan kunci eksplisit.

menyelesaikan

Masukkan deskripsi gambar di sini

  • Pipa-pipa tersebut diletakkan satu di depan cetakan dan satu lagi di belakang cetakan.
  • Jika Person2 dijalankan terlebih dahulu dan tidak ada data di dalam pipeline, maka akan diblokir.
  • Person1 mengeksekusi dan setelah mencetak data, memasukkan data ke dalam pipa. Person2 akan merasakannya dan mulai mencetak.

Menerapkan sinkronisasi dan interaksi data melalui saluran

Masukkan deskripsi gambar di sini
Masukkan deskripsi gambar di sini

saluran tanpa buffer

Saluran tanpa buffer adalah saluran yang tidak memiliki kemampuan untuk menyimpan nilai apa pun sebelum menerima.
Jenis saluran ini mengharuskan goroutine pengirim dan goroutine penerima siap pada saat yang sama untuk menyelesaikan operasi pengiriman dan penerimaan. Jika dua goroutine tidak siap pada saat yang sama, saluran tersebut akan menyebabkan goroutine yang melakukan operasi kirim atau terima terlebih dahulu memblokir dan menunggu.
Interaksi pengiriman dan penerimaan ke saluran ini pada dasarnya sinkron. Tidak ada satu operasi pun yang dapat berdiri sendiri-sendiri satu sama lain.
Gambar berikut menunjukkan bagaimana dua goroutine dapat berbagi nilai menggunakan saluran tanpa buffer:
Masukkan deskripsi gambar di sini

  • Artinya, saluran itu sendiri tidak dapat menyimpan sesuatu, jika Anda memasukkan sesuatu ke dalamnya, Anda dapat segera mengeluarkannya.
  • Pada langkah 1, kedua goroutine tiba di saluran, namun tidak ada yang mulai mengirim atau menerima.
  • Pada langkah 2, goroutine di sebelah kiri memasukkan tangannya ke dalam saluran, yang menyimulasikan tindakan pengiriman data ke saluran. Saat ini, goroutine akan dikunci di saluran hingga pertukaran selesai.
  • Pada langkah 3, goroutine di sebelah kanan memasukkan tangannya ke dalam saluran, yang menyimulasikan penerimaan data dari saluran. Goroutine ini juga akan dikunci di saluran hingga pertukaran selesai.
  • Pada langkah 4 dan 5, pertukaran terjadi, dan terakhir, pada langkah 6, kedua goroutine mengeluarkan tangannya dari saluran, yang menyimulasikan pelepasan goroutine yang terkunci. Kedua goroutine tersebut kini dapat melakukan hal lain.

Buat saluran tanpa buffer

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

Jika tidak ada ukuran buffer yang ditentukan, saluran tersebut sinkron dan oleh karena itu diblokir hingga pengirim siap mengirim dan penerima siap menerima.

Masukkan deskripsi gambar di sini

  • ch&lt;-i menulis data ke saluran, dan coroutine utama tidak akan dijalankan sampai ia merasakannya. Pada saat ini, sub-coroutine juga akan memblokir dan menunggu. Setelah pipa membaca data, sub-coroutine akan melanjutkan .
  • Namun println mencetak data setelah pipa dibaca, sehingga kecepatan pencetakan ditentukan oleh sistem.

saluran buffered

Saluran buffered adalah saluran yang dapat menyimpan satu atau lebih nilai sebelum diterima.
Jenis saluran ini tidak mengharuskan goroutine menyelesaikan pengiriman dan penerimaan secara bersamaan. Saluran juga akan memiliki kondisi berbeda yang memblokir tindakan pengiriman dan penerimaan. Tindakan penerimaan hanya akan diblokir jika tidak ada nilai dalam saluran yang akan diterima. Tindakan kirim hanya akan memblokir jika saluran tidak memiliki buffer yang tersedia untuk mengakomodasi nilai yang dikirim.
Hal ini menyebabkan perbedaan besar antara saluran yang di-buffer dan tidak di-buffer: saluran yang tidak di-buffer menjamin bahwa goroutine yang mengirim dan menerima akan bertukar data pada saat yang sama: saluran yang di-buffer tidak memiliki jaminan seperti itu.
Masukkan deskripsi gambar di sini

  • Pada langkah 1, goroutine di sebelah kanan menerima nilai dari saluran.
  • Pada langkah 2, goroutine di sebelah kanan menyelesaikan tindakan menerima nilai secara mandiri, sedangkan goroutine di sebelah kiri mengirimkan nilai baru ke saluran.
  • Pada langkah 3, goroutine di sebelah kiri masih mengirimkan nilai baru ke saluran, sedangkan goroutine di sebelah kanan menerima nilai lain dari saluran. Kedua operasi pada langkah ini tidak disinkronkan atau saling memblokir.
  • Terakhir, pada langkah 4, semua pengiriman dan penerimaan selesai, dan masih ada beberapa nilai di saluran dan beberapa ruang untuk menyimpan lebih banyak nilai.

membuat

make (chan Type,capacity)
  • 1

Jika kapasitas buffer diberikan, salurannya tidak sinkron. Selama buffer mempunyai ruang yang tidak terpakai untuk mengirim data atau berisi data yang dapat diterima, komunikasi akan berlangsung tanpa pemblokiran.

menyelesaikan

Masukkan deskripsi gambar di sini

  • Jika cukup tiga yang disimpan, maka akan diblokir dan menunggu pembacaan. Ketika coroutine utama telah membaca sebagian data dan ada ruang kosong, sub-coroutine akan terus dijalankan, dan urutan pencetakan berikutnya tidak akan pasti.
    Masukkan deskripsi gambar di sini

menutup saluran

Saluran dapat menggunakan ok untuk mendeteksi apakah saluran masih terbuka. Jika saluran ditutup, data tidak akan terbaca.

Masukkan deskripsi gambar di sini

  • num ,ok:=<-chDapat mendeteksi jika suatu saluran ditutup.

Melihat

  • Saluran tidak perlu sering ditutup seperti file. Tutup saluran hanya ketika Anda benar-benar tidak memiliki data untuk dikirim, atau jika Anda ingin secara eksplisit mengakhiri loop rentang atau sejenisnya;
  • Setelah menutup saluran, tidak ada lagi data yang dapat dikirim ke saluran (kesalahan panik dipicu, menyebabkan penerimaan segera mengembalikan nilai nol):
  • Setelah saluran ditutup, Anda dapat terus menerima data dari saluran:
  • Untuk saluran nihil, pengiriman dan penerimaan akan diblokir.
    Masukkan deskripsi gambar di sini
  • Anda dapat menggunakan jangkauan untuk melintasi saluran dan secara otomatis melompat keluar dari lingkaran
    Masukkan deskripsi gambar di sini

Saluran satu arah

Secara default, saluran tersebut memiliki pertanyaan ganda, yaitu, Anda dapat mengirim data ke saluran tersebut dan menerima data dari saluran tersebut.
Namun, kita sering melihat saluran dilewatkan sebagai parameter dan nilainya diharapkan digunakan dalam satu arah, baik hanya untuk mengirim data atau hanya untuk menerima data. Saat ini, kita dapat menentukan arah saluran. Deklarasi variabel chamel satu arah sangat sederhana, sebagai berikut:

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

chan&lt;- berarti data masuk ke pipa, dan data ditulis ke dalam pipa, yang dikeluarkan ke pemanggil.
&lt;-chan menandakan data yang keluar dari pipa. Bagi pemanggil, data dari pipa tersebut diperoleh, yang tentunya menjadi input.
Suatu saluran secara implisit dapat diubah menjadi antrian satu arah, hanya menerima atau mengirim saja, tetapi saluran satu arah tidak dapat diubah menjadi saluran normal;

Masukkan deskripsi gambar di sini

Memanfaatkan satu saluran untuk menerapkan model produsen-konsumen

Masukkan deskripsi gambar di sini