GolangチャネルChanの詳細について
まずスレッドを見てみましょうgolangでもgoroutineと呼ばれています
この文章を読む前に、同時と並列を理解する必要があります.golangのスレッドは並列ではなく同時メカニズムです.それらの違いはインターネットで検索することができ、ネット上では多くの紹介があります.
まず例を見てみましょう
golangでは、goというキーワードを使って、後に関数を1つ追加するとスレッドを作成できます.後ろのこの関数はすでに書いた関数でも匿名の関数でもいいです.
上のコードは匿名関数を作成し、パラメータiも入力します.下の括弧のiは実パラメータで、aは形パラメータです.
では、上のコードは私たちの予想通りに1、2、3を印刷できますか?教えてあげましょう.できません.プログラムは2しか印刷できません.次は正しいコードを貼り付けましょう
私は最後にメインスレッドを1秒休眠させるコードを追加しただけで、プログラムは
2、3、1を印刷します.どうしてこんなことになったの?プログラムはメインスレッドを優先的に実行するため、メインスレッドの実行が完了すると、プログラムはすぐに終了し、サブスレッドを実行する時間がありません.プログラムの最後にプライマリスレッドを1秒休止させると、サブスレッドを実行するのに十分な時間がかかります.
コースはまずここまでですが、次に通路を見てみましょう.
チャネルはchannelとも呼ばれ、その名の通り、channelの役割はマルチスレッド間でデータを伝達することです.
バッファなしchannelの作成
chreadandwrite :=make(chan int)
chonlyread:=make(chonlywrite:=make(chanの例を次に示します.
このコードを実行すると、fatal error:all goroutines are asleep-deadlockというエラーが発生します.
このエラーは、スレッドがデッドロックに陥り、プログラムが実行されないことを意味します.では、このような間違いの原因は何なのでしょうか.
バッファレスchannelを作成し、このchannelに値を割り当てました.プログラムは、値の割り当てが完了した後にデッドロックに陥りました.私たちのchannelはバッファがなく、同期しているので、割り当てが完了してからchannelを読み取ることができず、プログラムはブロックされています.ここでは非常に重要な概念を紹介します:channelのメカニズムは先進的に先に出て、もしあなたがchannelに値を割り当てたら、その値を読み取らなければなりません.そうしないと、ブロックをもたらします.もちろん、これはバッファのないchannelにしか有効ではありません.バッファ付きchannelの場合、送信者はデータがバッファにコピーされるまでブロックします.バッファが満たされている場合、送信者は受信者がデータを取り出した後にブロック状態から回復するしかありません.
上記の例では、2つのソリューションがあります.
1、channelにバッファを追加し、プログラムの最後にメインスレッドを1秒休止させます.コードは以下の通りです.
するとプログラムは1、2の順に印刷されます
2、chを
ここでは、メインスレッドをスリープさせる必要はありません.channelがメインスレッドに付与されると、メインスレッドは、channelの値がサブスレッドから取り出されるまでブロックされます.
最後に、生産者と消費者の例を見てみましょう.
このコードでは、channelはバッファリングされていないため、生産者がchannelに値を割り当てると、消費者スレッドがchannelのデータを取り出すまで、生産者というスレッドがブロックされます.消費者が初めてデータを取り出した後、次のサイクルを行うと、消費者のスレッドもブロックされます.生産者がまだデータを保存していないため、プログラムは生産者のスレッドを実行します.プログラムは,ループが終了するまで消費者と生産者の2つのスレッド間で絶えず切り替えられる.
次に、バッファ付きの例を見てみましょう.
このプログラムでは,バッファに10個のintタイプの整数を格納することができ,生産者スレッドを実行する際にスレッドがブロックされず,一度に10個の整数をchannelに格納し,読み取る際にも一度に読み出す.
また、以下を参照してください.http://www.qzblog.net/blog/605
この文章を読む前に、同時と並列を理解する必要があります.golangのスレッドは並列ではなく同時メカニズムです.それらの違いはインターネットで検索することができ、ネット上では多くの紹介があります.
まず例を見てみましょう
import(
"fmt"
)
funcmain(){
go fmt.Println("1")
fmt.Println("2")
}
golangでは、goというキーワードを使って、後に関数を1つ追加するとスレッドを作成できます.後ろのこの関数はすでに書いた関数でも匿名の関数でもいいです.
funcmain(){
var i=3
go func(a int) {
fmt.Println(a)
fmt.Println("1")
}(i)
fmt.Println("2")
}
上のコードは匿名関数を作成し、パラメータiも入力します.下の括弧のiは実パラメータで、aは形パラメータです.
では、上のコードは私たちの予想通りに1、2、3を印刷できますか?教えてあげましょう.できません.プログラムは2しか印刷できません.次は正しいコードを貼り付けましょう
import(
"fmt"
"time"
)
funcmain(){
var i = 3
go func(a int) {
fmt.Println(a)
fmt.Println("1")
}(i)
fmt.Println("2")
time.Sleep(1 * time.Second)
}
私は最後にメインスレッドを1秒休眠させるコードを追加しただけで、プログラムは
2、3、1を印刷します.どうしてこんなことになったの?プログラムはメインスレッドを優先的に実行するため、メインスレッドの実行が完了すると、プログラムはすぐに終了し、サブスレッドを実行する時間がありません.プログラムの最後にプライマリスレッドを1秒休止させると、サブスレッドを実行するのに十分な時間がかかります.
コースはまずここまでですが、次に通路を見てみましょう.
チャネルはchannelとも呼ばれ、その名の通り、channelの役割はマルチスレッド間でデータを伝達することです.
バッファなしchannelの作成
chreadandwrite :=make(chan int)
chonlyread:=make(chonlywrite:=make(chanの例を次に示します.
ch :=make(chan int)
ch 1
go func() {
"1")
}()
fmt.Println("2")
このコードを実行すると、fatal error:all goroutines are asleep-deadlockというエラーが発生します.
このエラーは、スレッドがデッドロックに陥り、プログラムが実行されないことを意味します.では、このような間違いの原因は何なのでしょうか.
バッファレスchannelを作成し、このchannelに値を割り当てました.プログラムは、値の割り当てが完了した後にデッドロックに陥りました.私たちのchannelはバッファがなく、同期しているので、割り当てが完了してからchannelを読み取ることができず、プログラムはブロックされています.ここでは非常に重要な概念を紹介します:channelのメカニズムは先進的に先に出て、もしあなたがchannelに値を割り当てたら、その値を読み取らなければなりません.そうしないと、ブロックをもたらします.もちろん、これはバッファのないchannelにしか有効ではありません.バッファ付きchannelの場合、送信者はデータがバッファにコピーされるまでブロックします.バッファが満たされている場合、送信者は受信者がデータを取り出した後にブロック状態から回復するしかありません.
上記の例では、2つのソリューションがあります.
1、channelにバッファを追加し、プログラムの最後にメインスレッドを1秒休止させます.コードは以下の通りです.
ch :=make(chan int,1)
ch 1
go func() {
v := (1 * time.Second)
fmt.Println("2")
するとプログラムは1、2の順に印刷されます
2、chを
ch :=make(chan int)
go func() {
v := 1
fmt.Println("2")
ここでは、メインスレッドをスリープさせる必要はありません.channelがメインスレッドに付与されると、メインスレッドは、channelの値がサブスレッドから取り出されるまでブロックされます.
最後に、生産者と消費者の例を見てみましょう.
import (
"fmt"
"time"
)
func produce(p chanint) {
for i := 0; i < 10; i++ {
p "send:", i)
}
}
func consumer(c chan int) {
for i := 0; i < 10; i++ {
v := "receive:", v)
}
}
func main() {
ch := make(chan int)
go produce(ch)
go consumer(ch)
time.Sleep(1 * time.Second)
}
このコードでは、channelはバッファリングされていないため、生産者がchannelに値を割り当てると、消費者スレッドがchannelのデータを取り出すまで、生産者というスレッドがブロックされます.消費者が初めてデータを取り出した後、次のサイクルを行うと、消費者のスレッドもブロックされます.生産者がまだデータを保存していないため、プログラムは生産者のスレッドを実行します.プログラムは,ループが終了するまで消費者と生産者の2つのスレッド間で絶えず切り替えられる.
次に、バッファ付きの例を見てみましょう.
import (
"fmt"
"time"
)
func produce(p chanint) {
for i := 0; i < 10; i++ {
p "send:", i)
}
}
func consumer(c chan int) {
for i := 0; i < 10; i++ {
v := "receive:", v)
}
}
func main() {
ch := make(chan int, 10)
go produce(ch)
go consumer(ch)
time.Sleep(1 * time.Second)
}
このプログラムでは,バッファに10個のintタイプの整数を格納することができ,生産者スレッドを実行する際にスレッドがブロックされず,一度に10個の整数をchannelに格納し,読み取る際にも一度に読み出す.
また、以下を参照してください.http://www.qzblog.net/blog/605