2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Coroutinum est filum leve-gradu usoris quod spatium acervum sui iuris habet et spatium cumulum programmatis communicat.
Micro-fila per algorithms in ex uno sequela comparata est, cum multi-filam programmandi comparata, sequentia commoda habet:
Channel data est structura ad communicationem inter coroutines adhibita. A queue similis, unus finis est mittenti et alter finis receptor. Usura canales efficere potest synchronisationem et ordinem notitiae.
Canales dividuntur in canales buffered et canales sineferos, qui hoc modo declarantur:
intChan := make(chan int,<缓冲容量>)
intChan := make(chan int)
Discrimen inter canales buffered et canales non effertos;
Quod notandum est in exsequendis canalibus intemperatis est mittente et receptore ad utrumque alveum esse oportere, alioquin morticinum erit.
Quaeritur significatio: Utere canali coroutino ad imprimendos numeros alternatim 1-10 et litteras AJ.
Codicis:
- package main
-
- import (
- "fmt"
- "sync"
- )
-
- /*
- 无缓冲chanel:需要在写入chanel的时候要保证有另外一个协程在读取chanel。否则会导致写端阻塞,发生死锁
- 解决办法:
- 避免死锁的发生:
- 当i循环到10时,printAlp协程已然结束,所以此时不必再写入alp通道
- */
-
- func printNum(wg *sync.WaitGroup, numCh chan struct{}, alpCh chan struct{}) {
- defer wg.Done()
-
- for i := 1; i <= 10; i++ {
- <-alpCh // 等待字母goroutine发信号
- fmt.Print(i, " ")
- //避免死锁发生
- if i < 10 {
- numCh <- struct{}{} // 发信号给字母goroutine
- }
- if i == 10 {
- close(numCh)
- }
- }
-
- }
-
- func printAlp(wg *sync.WaitGroup, numCh chan struct{}, alpCh chan struct{}) {
- defer wg.Done()
-
- for i := 'A'; i <= 'J'; i++ {
- <-numCh // 等待数字goroutine发信号
- fmt.Printf("%c", i)
- alpCh <- struct{}{} // 发信号给数字goroutine
- }
- close(alpCh)
- }
-
- func main() {
- numCh := make(chan struct{}) // 用于数字goroutine的信号通道
- alpCh := make(chan struct{}) // 用于字母goroutine的信号通道
- var wg sync.WaitGroup
-
- wg.Add(2)
-
- go printAlp(&wg, numCh, alpCh)
- go printNum(&wg, numCh, alpCh)
-
- // 启动时先给数字goroutine发送一个信号
- numCh <- struct{}{}
-
- wg.Wait()
-
- }
Analysis topic:
Interrogatio nos postulat ut epistolas et numeros alternatim imprimant, ut necesse sit ut ordo districtus duorum coroutinorum, qui applicatione canalium non effusorum missione congruat. Duos canales constitue ut numeros et litteras respective condant. Imprime semel in ansa et signum mittat semel ut alium coroutinum imprimat admoneat.
Animadvertendum est, cum ultima characteris "10" impressus est, coroutinum litterarum imprimendi finivit, et numCh alveus non habet receptorem. Hoc tempore, condiciones exsecutionis canalis gratis non amplius convenerunt - oportet esse Mittens et Receptaculum. Alioquin mittens signum iterum claudendi causa deadlock. Itaque non est necesse ut signum iterum 10 tempore mittat.
Title: Designa munus scheduler quod utitur exemplo programmandi multi-coroutine + canalis ad negotium deducendi missiones concurrentis processus multi- munerum, et requirit schedulingum ordinem quo adduntur opera.
Codicis:
- type scheduler struct {
- taskChan chan func()
- wt sync.WaitGroup
- }
-
- func (td *scheduler) AddTask(task func()) {
- td.taskChan <- task
- }
-
- func (td *scheduler) Executer() {
- defer td.wt.Done()
- for {
- task, ok := <-td.taskChan
- task()
- if ok && len(td.taskChan) == 0 {
- break
- }
- }
- }
-
- func (td *scheduler) Start() {
- td.wt.Add(4)
- //假设四个消费者
- for i := 0; i < 4; i++ {
- go td.Executer()
- }
-
- td.wt.Wait()
- }
-
- func main() {
- sd := scheduler{
- taskChan: make(chan func(), 5),
- }
-
- go func() {
- sd.AddTask(func() {
- fmt.Println("任务1")
- })
- sd.AddTask(func() {
- fmt.Println("任务2")
- })
- sd.AddTask(func() {
- fmt.Println("任务3")
- })
- sd.AddTask(func() {
- fmt.Println("任务4")
- })
- sd.AddTask(func() {
- fmt.Println("任务5")
- })
- sd.AddTask(func() {
- fmt.Println("任务6")
- })
- close(sd.taskChan)
- }()
-
- sd.Start()
-
- }
quaestio analysis:
Cum multae functiones additae sint, plus quam unum est, et processus asynchronus ad haec munera exercenda requiritur. Obsequor canalibus buffered emendatis throughput et asynchronous processui requirit.
Tum opus in canalem imponere oportet, multique accipientes munus ab alveo accipere possunt ut ea exequantur et exsequantur.
Problema, quod attentione indiget, est quod, si numerus operum additorum maior est quam quiddam canalis, obturationem faciet cum muneribus additis. Ut normalem satus of perussi non afficit, coroutine separatum aperire debet opera addere.
Hoc modo, cum consumit edax, effectrix interclusio excitabitur ad operas addendo.
Postquam exemplar programmationis coroutine + canalis pervestigamus, praeter ea quae in titulo proxime nominata sunt, etiam ad quaestiones sequentes attendendum debemus:
Ante omnia, principium principalissimum canalium claudendi non est claudere canales clausis. Secundo est aliud principium utendi canales Go;Noli claudere canalem in notitia accipientis vel cum plures sunt mittentes.in aliis verbis,Tantum canalem mittentem solum hunc canalem claudere debemus.
Via rudis est claudere canalem per receptam exceptionem, sed manifesto illa principia violat, et genus notitiarum causare potest; alius modus est sync. Mutex claudere canalem operationes et operationes in canalem mittere non faciunt data gentes. Utriusque modi problemata quaedam habent, ideo eas singillatim non introducebo. Hic modus est quomodo canalem lepide claudat.
Una ex facillimis adiunctis euenit. Cum mittens necesse est ut mittendo perficiat, canalem mox claudat. Ita est in duobus programmatis exemplis.
Secundum principia fundamentalia Canalium Go, solum possumus canalem claudere ad unicum mittente canalis. Ita, hoc casu, alveum alicubi directe claudere non possumus.Sed accipientem prope canalem additicium signum permittere possumus ut mittente non amplius notitias mitteret.。
- package main
-
- import (
- "log"
- "sync"
- )
-
- func main() {
-
- cosnt N := 5
- cosnt Max := 60000
- count := 0
-
- dataCh := make(chan int)
- stopCh := make(chan bool)
-
- var wt sync.WaitGroup
- wt.Add(1)
-
- //发送者
- for i := 0; i < N; i++ {
- go func() {
- for {
- select {
- case <-stopCh:
- return
- default:
- count += 1
- dataCh <- count
- }
- }
- }()
- }
-
- //接收者
- go func() {
- defer wt.Done()
- for value := range dataCh {
- if value == Max {
- // 此唯一的接收者同时也是stopCh通道的
- // 唯一发送者。尽管它不能安全地关闭dataCh数
- // 据通道,但它可以安全地关闭stopCh通道。
- close(stopCh)
- return
- }
- log.Println(value)
- }
- }()
-
- wt.Wait()
- }
Hoc pacto addito canali stopCh signo addito, quo receptor utitur ad mittente indicandam notitias recipere non amplius oportere. Haec autem methodus dataCh non claudit. Cum canalis coroutine nulla amplius adhibetur, paulatim coeno colligitur, quantumvis occlusum est.
Elegantia huius methodi est ut unum alveum claudendo, alio canali uti desinas, ita alterum alveum oblique claudendo.
Accipientem vel mittentem prope canalem habere non possumus, qui notitias tradendas adhibebat, nec unum ex multis receptoribus habere possumus, accessionem canalem significationis prope. Utrumque horum usuum principium clausurae canalis violant.
Sed inducere possumusIntermedium munus intermedium et additos canales significationis claudat ut omnes receptores et mittentes finis operis certiorem faciat.。
Exemplum codicis:
- package main
-
- import (
- "log"
- "math/rand"
- "strconv"
- "sync"
- )
-
- func main() {
-
- const Max = 100000
- const NumReceivers = 10
- const NumSenders = 1000
-
- var wt sync.WaitGroup
- wt.Add(NumReceivers)
-
- dataCh := make(chan int)
- stopCh := make(chan struct{})
- // stopCh是一个额外的信号通道。它的发送
- // 者为中间调解者。它的接收者为dataCh
- // 数据通道的所有的发送者和接收者。
- toStop := make(chan string, 1)
- // toStop是一个用来通知中间调解者让其
- // 关闭信号通道stopCh的第二个信号通道。
- // 此第二个信号通道的发送者为dataCh数据
- // 通道的所有的发送者和接收者,它的接收者
- // 为中间调解者。它必须为一个缓冲通道。
-
- var stoppedBy string
-
- // 中间调解者
- go func() {
- stoppedBy = <-toStop
- close(stopCh)
- }()
-
- // 发送者
- for i := 0; i < NumSenders; i++ {
- go func(id string) {
- for {
- value := rand.Intn(Max)
- if value == 0 {
- // 为了防止阻塞,这里使用了一个尝试
- // 发送操作来向中间调解者发送信号。
- select {
- case toStop <- "发送者#" + id:
- default:
- }
- return
- }
-
- select {
- case <-stopCh:
- return
- case dataCh <- value:
- }
- }
- }(strconv.Itoa(i))
- }
-
- // 接收者
- for i := 0; i < NumReceivers; i++ {
- go func(id string) {
- defer wt.Done()
-
- for {
- select {
- case <-stopCh:
- return
- case value := <-dataCh:
- if value == Max {
- // 为了防止阻塞,这里使用了一个尝试
- // 发送操作来向中间调解者发送信号。
- select {
- case toStop <- "接收者:" + id:
- default:
- }
- return
- }
-
- log.Println(value)
- }
- }
- }(strconv.Itoa(i))
- }
-
- wt.Wait()
- log.Println("被" + stoppedBy + "终止了")
-
- }