ホームページ >バックエンド開発 >Golang >学んだ!バッファリングされたチャネルをミューテックスとして使用する

学んだ!バッファリングされたチャネルをミューテックスとして使用する

Golang菜鸟
Golang菜鸟転載
2023-08-08 16:21:141370ブラウズ


#公式 Go パッケージの一部として、同期パッケージには次のステートメントがあります:

同期パッケージは、ミューテックス ロックなどの基本的な同期プリミティブを提供します。 Once 型と WaitGroup 型を除き、他のほとんどの型は、基礎となる関数ライブラリ用に設計されています。より高いレベルの同期は、チャネルと通信を通じてより適切に実現されます。

同時アクセスを許可する例の大部分では、問題を解決するためにミューテックスが使用されています。ただし、チャネルを使用して同期メカニズムを提供する方法を示す例はほとんどありません。そこで、この記事でそれについて説明しましょう。

ミューテックス ロックの特性

ミューテックス ロックが機能するには、共有変数にアクセスするときにロックする必要があります。操作が完了したらロックを解除する必要があります。競合状態を避けるために、同じミューテックスを複数回ロックすることはできません。

バッファリングされていないチャネルとその欠点

受信者が存在しない場合、送信者はブロックします。同様に、送信者が存在しない場合、受信者はブロックします。ブロックします。この特性に基づいて、バッファリングされていないチャネルをロックとして使用することはできません。

バッファ チャネルをミューテックス ロックとして使用できるかどうかを見てみましょう。

バッファ サイズ 1 のチャネルの特性と利点

バッファ サイズ 1 のチャネルには次の特性があります。バッファがいっぱいの場合は送信時にブロックされ、キャッシュが空の場合は送信時にブロックが解除されます。

明らかに、このチャネルのブロック特性は望ましいものです。ミューテックス ロックの特性と比較してください:

バッファがいっぱいになったときにロックする71fb34173e4ee87dab1f85dc1c283a44

Buffer休暇71fb34173e4ee87dab1f85dc1c283a44 ロック解除

コードを通じてこの機能を実証してみましょう。

デモ: バッファ チャネルを「ロック」として使用する方法

バッファ チャネルに書き込む必要がある名前の列があると仮定します。ファイルには、それぞれの名前が連続して 1000 回書き込む必要があり、異なる名前間の重複は許可されません。

package main
import (
 "errors"
 "fmt"
 "os"
 "sync"
)
func main() {
 file, err := os.Create("record.txt")

 defer func() {
  if err := recover(); err != nil {
   fmt.Printf("Error encounter: %w", err)
  }
  file.Close()
 }()
 if err != nil {
  panic(errors.New("Cannot create/open file"))
 }
 ss := []string{ //string slice literals
  "James",
  "Avery",
  "Peter",
  "John",
  "Beau",
 }
 chanLock := make(chan int, 1) //1
 var wg sync.WaitGroup
 for _, str := range ss { //2
  wg.Add(1) //amended thanks to response from Wang
  //Sheng
  go func(aString string) {

   chanLock <- 1 //3
   for i := 0; i < 1000; i++ {
    file.WriteString(aString + "\n")
   }
   <-chanLock //4
   wg.Done() //5
  }(str) //pass by value
 }
 wg.Wait()
}

上記のコードでは、 //1 バッファー 1 を持つチャネルを作成しました。 //2 名前の数と同じ数のゴルーチンを作成しました。 //3 はロックに相当し、 //4 はロック解除に相当します。そのため、複数のゴルーチンが同期的に Record.txt ファイルに名前を書き込むことができますが、ファイルを操作できるのは一度に 1 つのゴルーチンだけです。

サブゴルーチンがタスクを完了する前にメイン コルーチンが終了しないようにするために WaitGroup を使用していることに注意してください。

この記事がお役に立てば幸いです。コーディングをお楽しみください!

以上が学んだ!バッファリングされたチャネルをミューテックスとして使用するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はGolang菜鸟で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。