


Program Go berfungsi dengan saluran tunggal dan menemui jalan buntu apabila saluran baharu diperkenalkan
Dalam bahasa Go, operasi serentak program dilaksanakan melalui saluran. Saluran ialah jenis khas yang digunakan untuk memindahkan data Ia membolehkan pertukaran data dan komunikasi antara goroutine. Walau bagaimanapun, jika anda bekerja dengan satu saluran dalam program anda dan tidak mengendalikannya dengan betul semasa memperkenalkan saluran baharu, kebuntuan mungkin berlaku. Dalam artikel ini, editor PHP Xiaoxin akan menerangkan secara terperinci tentang kerja saluran tunggal dan isu kebuntuan dalam program Go, dan cara mengelakkan kebuntuan.
Kandungan soalan
Saya baru menggunakan saluran Go dan saya cuba mempelajari saluran Go dengan membina inti tiruan dan mengendalikan interaksi melalui saluran. Matlamat program contoh ini adalah untuk mempunyai berbilang proses (2) secara serentak menghantar permintaan peruntukan memori ke kernel menggunakan saluran tunggal, dan proses lain untuk menghantar melepaskan permintaan memori ke kernel menggunakan saluran tunggal tetapi berbeza .
+-------------+ +------------------+ | | -> Alloc. Mem. Ch. |<--\ | | +-----------------+ ---/ +------------------+ >-->| Kernel | | Process A |<-- +------------------+ -/ | | +-----------------+ \--> | Realse Mem. Ch. |< | | +------------------+ +-------------+
Jika saya hanya mempunyai permintaan peruntukan, program berfungsi, sebaik sahaja saya memperkenalkan permintaan keluaran, program akan menemui jalan buntu.
Perhatikan bahawa proses itu juga mencipta baris gilir balasan apabila menghantar permintaan peruntukan, namun, ini tidak ditunjukkan dalam imej di atas kerana ia bukan sebahagian daripada masalah.
Prosedur lengkap adalah seperti berikut:
package main import ( "fmt" // "log" "time" ) const ( _ float64 = iota LowPrio MedPrio HghPrio ) // Kernel type to communicate between processes and memory resources type Kernel struct { reqMemCh chan chan int rlsMemCh chan int } func (k *Kernel) Init() { k.reqMemCh = make(chan chan int, 2) k.rlsMemCh = make(chan int, 2) go k.AllocMem() go k.RlsMem() } // Fetch memory on process request func (k *Kernel) GetReqMemCh() chan chan int { return k.reqMemCh } func (k *Kernel) GetRlsMemCh() chan int { return k.rlsMemCh } func (k *Kernel) AllocMem() { // loop over the items (process reply channels) received over // the request channel for pCh := range k.GetReqMemCh() { // for now think 0 is the available index // send this as a reply to the exclusive process reply channel pCh <- 0 close(pCh) } } // Release memory func (k *Kernel) RlsMem() { // we do not have to anything here } // Process type which requests memory type Proc struct { ind int prio float64 exeT time.Time count int memInd int rqMemCh chan chan int rlMemCh chan int } func (p *Proc) Init( ind int, prio float64, rqMemCh chan chan int, rlMemCh chan int, ) { p.ind = ind p.prio = prio p.memInd = -1 p.rqMemCh = rqMemCh p.rlMemCh = rlMemCh } func (p *Proc) GetReqMemCh() chan chan int { return p.rqMemCh } func (p *Proc) GetRlsMemCh() chan int { return p.rlMemCh } func (p *Proc) ReqMem() { // create the reply channel exclusive to the process // this channel will return the allocated memeory id/address rpCh := make(chan int) // send the reply channel through the request channel // to get back the allocation memory id p.GetReqMemCh() <- rpCh // Below line is blocking ... for mi := range rpCh { p.memInd = mi } } func (p Proc) RlsMem() { p.GetRlsMemCh() <- 0 } func (p Proc) String() string { return fmt.Sprintf( "Proc(%d): Memory(%d), Count(%d)", p.ind+1, p.memInd+1, p.count, ) } func main() { k := &Kernel{} k.Init() p := &Proc{} for i := 0; i < 3; i++ { p.Init(i, LowPrio, k.GetReqMemCh(), k.GetRlsMemCh()) p.ReqMem() p.RlsMem() } time.Sleep(time.Second) }
Pengecualian adalah seperti berikut:
fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan send]: main.Proc.RlsMem(...) main.go:100 main.main() main.go:119 +0xc5 goroutine 6 [chan receive]: main.(*Kernel).AllocMem(0x0?) main.go:41 +0x5e created by main.(*Kernel).Init in goroutine 1 main.go:25 +0xc5 exit status 2
Sebarang bantuan amat kami hargai.
Sekian,
DD.
Penyelesaian
Sebagai Pengulas Inggeris, anda mempunyai saluran penimbal yang telah mencapai kapasitinya tetapi tiada apa-apa untuk dibaca.
Mengikut lawatan bahasa (1 2), hantar dan terima blok sehingga pihak lain bersedia. Walaupun saluran penimbal memberikan sedikit toleransi di sini, setelah penimbal penuh, gelagatnya adalah sama.
Masalah ini boleh diselesaikan dengan menambah pengguna k.rlsMemCh
. Jika anda tidak mempunyai apa-apa rancangan untuk ini, padamkan saluran atau gunakan logik untuk mengalirkannya buat sementara waktu.
<code>func (k *Kernel) Init() { k.reqMemCh = make(chan chan int, 2) k.rlsMemCh = make(chan int, 2) go k.AllocMem() go k.RlsMem() } func (k *Kernel) AllocMem() { for pCh := range k.GetReqMemCh() { pCh <- 0 close(pCh) } } func (k *Kernel) RlsMem() { // TODO: Add a for-select or for-range over k.rlsMemCh here } </code>
Parit mungkin kelihatan seperti ini:
func (k *Kernel) RlsMem() { for { <-k.GetRlsMemCh() } }
Atas ialah kandungan terperinci Program Go berfungsi dengan saluran tunggal dan menemui jalan buntu apabila saluran baharu diperkenalkan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Perpustakaan yang digunakan untuk operasi nombor terapung dalam bahasa Go memperkenalkan cara memastikan ketepatannya ...

Masalah Threading Giliran di GO Crawler Colly meneroka masalah menggunakan Perpustakaan Colly Crawler dalam bahasa Go, pemaju sering menghadapi masalah dengan benang dan permintaan beratur. � ...

Perpustakaan mana yang dibangunkan oleh syarikat besar atau projek sumber terbuka yang terkenal? Semasa pengaturcaraan di GO, pemaju sering menghadapi beberapa keperluan biasa, ...

Masalah menggunakan redisstream untuk melaksanakan beratur mesej dalam bahasa Go menggunakan bahasa Go dan redis ...

Perbezaan antara percetakan rentetan dalam bahasa Go: perbezaan kesan menggunakan fungsi println dan rentetan () sedang ...

GO Pointer Syntax dan menangani masalah dalam penggunaan perpustakaan Viper semasa pengaturcaraan dalam bahasa Go, adalah penting untuk memahami sintaks dan penggunaan petunjuk, terutama dalam ...

Kaedah penyesuaian simbol saiz semula dalam CSS bersatu dengan warna latar belakang. Dalam perkembangan harian, kita sering menghadapi situasi di mana kita perlu menyesuaikan butiran antara muka pengguna, seperti menyesuaikan ...

Mengapa lelaran peta di GO menyebabkan semua nilai menjadi elemen terakhir? Dalam bahasa Go, ketika berhadapan dengan beberapa soalan wawancara, anda sering menemui peta ...
