Golang は、効率的で高性能な並列分散プログラムを構築するために広く使用されているプログラミング言語です。シンプルで軽量な構文という利点があり、並行プログラミングを簡単に使用できます。
Golang では、ゴルーチンとチャネルを使用して同時プログラミングを実装するのが一般的な方法です。 Goroutine は Golang 独自の軽量スレッドで、単一スレッドで複数のタスクを同時に実行でき、タスクがブロックされていない場合はオーバーヘッドゼロで切り替えることができます。チャネルは、複数のゴルーチンが連携してデータ転送とタスク間の同期を完了できるようにする同期プリミティブです。
一般的な Golang 同時プログラミング スキルを見てみましょう:
1. goroutine を使用して同時実行を実現します
Golang の Goroutine は非常に使いやすく、必要なのは次のことだけです。関数を呼び出す前に goroutine を使用する 「go」キーワードを追加すると、それが goroutine になります。例:
func main() { //启动一个新的goroutine go func() { fmt.Println("Hello World") }() //在这里继续执行其他任务 //... }
上記のコードは、別のスレッドで「Hello World」を出力し、同時に main 関数の実行を継続します。 goroutine を使用すると、プログラムの同時実行性と応答速度が大幅に向上します。
2. チャネルを使用してデータ同期を実現する
Golang のチャネルは、複数のゴルーチン間でデータを転送し同期するために使用される同期プリミティブです。チャネルは任意の 2 つのゴルーチン間の通信を確立でき、メッセージの送受信にはブロッキングとノンブロッキングの 2 つの方法があります。
次は、チャネルを使用してデータを転送する簡単な例です:
func main() { //创建一个整数类型的channel ch := make(chan int) //启动一个goroutine发送数据 go func() { ch <- 123 //发送数据到channel中 }() //接收刚刚发送的数据 num := <- ch //从channel中接收数据 fmt.Println(num) //输出:123 }
上記のコードでは、最初に整数型のチャネルを作成します。次に、ゴルーチンが開始されてデータが送信され、メインスレッドのチャネルからデータが受信されて出力されます。チャネルを使用すると、異なるゴルーチン間でデータを転送および同期できます。
3. 同期パッケージを使用して同期を実現します
sync は、Mutex、RWMutex、Cond、Once、WaitGroup などを含む、Golang の同期プリミティブのコレクションです。より高度な同期とスレッドセーフティ制御を実装するために使用できます。
Mutex は、共有リソースを保護するために使用されるミューテックス ロックです。クリティカルセクションにアクセスする前に Lock() 関数を使用してミューテックスを取得し、アクセスが完了した後に Unlock() 関数を使用してロックを解放します。
以下は、Mutex を使用して実装されたスレッドセーフ カウンタの例です:
import ( "fmt" "sync" ) type Counter struct { count int mu sync.Mutex } func (c *Counter) Increment() { //获取互斥锁并增加计数 c.mu.Lock() c.count++ c.mu.Unlock() } func (c *Counter) Count() int { //获取互斥锁并返回计数 c.mu.Lock() defer c.mu.Unlock() return c.count } func main() { //创建一个计数器 c := Counter{} //启动多个goroutine增加计数 for i := 0; i < 1000; i++ { go c.Increment() } //等待所有goroutine执行完成 time.Sleep(time.Second) //输出计数器的值 fmt.Println(c.Count()) }
上記のコードでは、Mutex を使用してカウンタ共有リソースを保護し、複数の場合でも安全であることを確認します。 goroutine は同時に実行されます。スレッド セーフ。
4. コンテキスト パッケージを使用してタイムアウト制御を実装する
Golang では、コンテキストはゴルーチン サブツリーの動作を制御するために使用される推移的なコンテキストです (Java の ThreadLocal に似ています)。
コンテキスト パッケージは、Goroutine コンテキスト管理を開始するために使用できる、WithCancel()、WithDeadline()、WithTimeout() などのいくつかの関数を提供します。これらの関数は、新しいコンテキスト オブジェクトと、コンテキストをキャンセルする必要があるときにコンテキストをキャンセル済みとしてマークするために呼び出すことができる関数を返します。 goroutine では、Context の Done() チャネルを使用してキャンセル信号を取得できます。
以下は、コンテキストを使用して実装されたタイムアウト制御の例です:
import ( "fmt" "context" ) func main() { //创建一个带超时的上下文 ctx, cancel := context.WithTimeout(context.Background(), time.Second) //执行一个耗时任务 go func() { time.Sleep(time.Second * 2) fmt.Println("Goroutine Done") }() //等待上下文取消信号 select { case <-ctx.Done(): fmt.Println("Timeout") } //取消上下文 cancel() }
上記のコードでは、まずタイムアウトが 1 秒のコンテキストを作成し、2 秒かかるコンテキストを開始しました。 goroutineを実行後、main関数内でコンテキストのDone()チャネルを待ち、キャンセル信号を受信すると「Timeout」が出力されます。
5. sync/atomic を使用して競合中にアトミック操作を実装する
Golang では、sync/atomic パッケージは、競合中に共有整数を更新するために使用できるいくつかのアトミック操作関数を提供します。価値。アトミック操作を使用すると、複数のゴルーチンが同時に実行される場合の競合状態を回避できます。
以下は、sync/atomic パッケージを使用して 16 進カウンタを出力するアトミック操作の例です。
import ( "fmt" "sync/atomic" ) func main() { //定义一个uint32的计数器 var counter uint32 //启动多个goroutine更新计数器 for i := 0; i < 1000; i++ { go func() { //原子地增加计数器 atomic.AddUint32(&counter, 1) }() } //等待所有goroutine执行完成 time.Sleep(time.Second) //输出计数器的值 fmt.Printf("0x%x\n", atomic.LoadUint32(&counter)) }
上記のコードでは、uint32 タイプのカウンタを定義し、AddUint32( ) 関数は、複数のゴルーチンが同時に実行されるときにカウントをアトミックにインクリメントします。最後に、カウンターの 16 進値が出力されます。
まとめ:
Golang の並行プログラミングは、シンプル、軽量、高性能という特徴があり、ゴルーチン、チャネル、同期などのツール機能を使用することで、スレッド間の連携が可能になります。プログラムの同時実行性能や応答速度を向上させる通信を容易に実現します。同時に、スレッドの安全性の問題を回避するために、同期メカニズムの使用に注意を払う必要があります。
以上が一般的に使用される Golang 同時プログラミング手法について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。