Go でのタイムアウトによるロック
Go でのロックの取得は、特にレイテンシーに対処する場合に問題が発生する可能性があります。 -機密性の高い操作。 sync.Mutex インターフェイスは、基本的なロックおよびロック解除機能のみを提供し、条件付きまたは指定された時間枠内でロックを取得する機能はありません。
ミューテックスとしてチャネルを使用する:
シンプルで効果的な解決策は、チャネルを相互排他プリミティブとして利用することです。バッファ サイズ 1 のチャネルを作成すると、ロックをシミュレートできます:
<code class="go">l := make(chan struct{}, 1)</code>
ロック:
ロックを取得するには、シグナルをチャンネル:
<code class="go">l <- struct{}{}</code>
ロック解除:
ロックを解除するには、チャンネルから受信します:
<code class="go"><-l</code>
ロックを試行:
タイムアウトを使用してロックを試みるには、select ステートメントを使用します。
<code class="go">select { case l <- struct{}{}: // lock acquired <-l default: // lock not acquired }</code>
このアプローチと time.After() を組み合わせることで、期限付きの TryLock を実装できます。
<code class="go">select { case l <- struct{}{}: // lock acquired <-l case <-time.After(time.Minute): // lock not acquired }</code>
例 1: 遅延に敏感な操作の制限
<code class="go">func (s *RPCService) DoTheThing(ctx context.Context, ...) ... { if AcquireLock(ctx.Deadline(), &s.someObj[req.Parameter].lock) { defer ReleaseLock(&s.someObj[req.Parameter].lock) ... expensive computation ... } else { return s.cheapCachedResponse[req.Parameter] } }</code>
例 2: タイムアウトによる統計の更新
<code class="go">func (s *StatsObject) updateObjStats(key, value interface{}) { if AcquireLock(200*time.Millisecond, &s.someObj[key].lock) { defer ReleaseLock(&s.someObj[key].lock) ... update stats ... ... fill in s.cheapCachedResponse ... } } func (s *StatsObject) UpdateStats() { s.someObj.Range(s.updateObjStats) }</code>
このアプローチにより、パフォーマンスとリソース使用率の問題を効果的に処理しながら、条件付きでロックを取得できます。
以上がチャネルを使用して Go でタイムアウト付きのロックを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。