Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 8011

Goメモ-497 (RWMutex.TryLock/TryRLock)(ロック取得をノンブロッキングに) - いろいろ備忘録日記

$
0
0

関連記事

Goメモ-496 (mutex.TryLock)(ロック取得をノンブロッキングに) - いろいろ備忘録日記

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

前回Mutex.TryLockについてメモしたのですが、sync.RWMutexについても RWMutex.TryLockRWMutex.TryRLockが追加されています。使い方は同じです。

サンプル

rwmutex_trylock.go

package syncs

import (
    "context""log""sync""time"
)

// RWMutexTryLock は、Go 1.18 で追加された RWMutex の TryLock() と TryRLock() のサンプルです。//// 使い方としては、Mutex.TryLock() と同じ。RLockのTry版がTryRLock, LockのTry版がTryLockとなる。//// # REFERENCES//   - https://pkg.go.dev/sync@go1.22.1#RWMutex.TryLock//   - https://pkg.go.dev/sync@go1.22.1#RWMutex.TryRLockfunc RWMutexTryLock() error {
    //// 3つのゴルーチンがあり、2つは値の読み取り(RLock)、1つは値の書き込み(Lock)を行う。// それぞれ、ロックに入る前に TryRLock/TryLock により、ロック可能かどうかを確認する。//

    log.SetFlags(log.Lmicroseconds)

    var (
        v    int64
        m    sync.RWMutex
        read = func(ctx context.Context, prefix string, interval time.Duration) {
            for {
                select {
                case<-ctx.Done():
                    returndefault:
                }

                func() {
                    log.Printf("[%s] <<<", prefix)
                    for !m.TryRLock() {
                        log.Printf("[%s] TryRLock=false", prefix)

                        select {
                        case<-ctx.Done():
                            returncase<-time.After(100 * time.Millisecond):
                        }
                    }

                    log.Printf("[%s] %v", prefix, v)

                    m.RUnlock()
                    log.Printf("[%s] >>>", prefix)

                    select {
                    case<-ctx.Done():
                    case<-time.After(interval):
                    }
                }()
            }
        }
        write = func(ctx context.Context, prefix string, interval time.Duration) {
            for {
                select {
                case<-ctx.Done():
                    returndefault:
                }

                func() {
                    log.Printf("[%s] <<<", prefix)
                    for !m.TryLock() {
                        log.Printf("[%s] TryLock=false", prefix)

                        select {
                        case<-ctx.Done():
                            returncase<-time.After(100 * time.Millisecond):
                        }
                    }

                    old := v
                    v++
                    log.Printf("[%s] %v --> %v", prefix, old, v)

                    m.Unlock()
                    log.Printf("[%s] >>>", prefix)

                    select {
                    case<-ctx.Done():
                    case<-time.After(interval):
                    }
                }()
            }
        }
    )

    ctx, cxl := context.WithTimeout(context.Background(), 2*time.Second)
    defer cxl()

    go read(ctx, "READ-1", 500*time.Millisecond)
    go read(ctx, "READ-2", 500*time.Millisecond)
    go write(ctx, "WRITE-1", 500*time.Millisecond)

    <-ctx.Done()
    log.Println("DONE")

    returnnil
}

実行

$ task
task: [build] go build .
task: [run] ./try-golang -onetime

ENTER EXAMPLE NAME: syncs_rwmutex_trylock

[Name]"syncs_rwmutex_trylock"
06:00:30.134950[WRITE-1]<<<
06:00:30.135052[WRITE-1]0-->1
06:00:30.135059[WRITE-1]>>>
06:00:30.134976[READ-2]<<<
06:00:30.135079[READ-2]1
06:00:30.135085[READ-2]>>>
06:00:30.134970[READ-1]<<<
06:00:30.135264[READ-1]1
06:00:30.135268[READ-1]>>>
06:00:30.635750[READ-1]<<<
06:00:30.635773[READ-1]1
06:00:30.635776[READ-1]>>>
06:00:30.635762[READ-2]<<<
06:00:30.635803[READ-2]1
06:00:30.635812[READ-2]>>>
06:00:30.635787[WRITE-1]<<<
06:00:30.635855[WRITE-1]1-->2
06:00:30.635867[WRITE-1]>>>
06:00:31.136388[WRITE-1]<<<
06:00:31.136406[READ-1]<<<
06:00:31.136411[WRITE-1]2-->3
06:00:31.136423[WRITE-1]>>>
06:00:31.136422[READ-2]<<<
06:00:31.136430[READ-2]3
06:00:31.136438[READ-2]>>>
06:00:31.136415[READ-1]TryRLock=false
06:00:31.236739[READ-1]3
06:00:31.236767[READ-1]>>>
06:00:31.637314[WRITE-1]<<<
06:00:31.637340[READ-2]<<<
06:00:31.637367[READ-2]TryRLock=false
06:00:31.637335[WRITE-1]3-->4
06:00:31.637405[WRITE-1]>>>
06:00:31.737604[READ-2]4
06:00:31.737631[READ-2]>>>
06:00:31.737631[READ-1]<<<
06:00:31.737644[READ-1]4
06:00:31.737653[READ-1]>>>
06:00:32.135034 DONE


[Elapsed]2.000177751s

参考情報

github.com

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。


Viewing all articles
Browse latest Browse all 8011

Trending Articles