ホームページ  >  記事  >  バックエンド開発  >  golangでファイルロックを実装する方法

golangでファイルロックを実装する方法

青灯夜游
青灯夜游オリジナル
2022-12-19 11:03:064913ブラウズ

golang では、同期パッケージの API を使用してファイル ロックを実装できます。ファイル ロック (flock) は、ファイル全体に対する勧告的ロックです。つまり、プロセスがファイル (inode) にロックを設定すると、他のプロセスはそれを知ることができます (勧告的ロックは、プロセスの準拠を強制しません)、ファイル ロックの呼び出し構文は「syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)」です。

golangでファイルロックを実装する方法

このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。

Go 言語を使用してプログラムを開発する場合、複数のプロセスが同じファイルに対して同時に動作することがよくあり、ファイル内のデータが混乱しやすくなります。このとき、これらの矛盾を何らかの手段でバランスさせる必要があり、ファイルロック(flock)が登場しましたので、以下に紹介しましょう。

flock の場合、最も一般的な例は Nginx です。プロセスの実行後、現在の PID がこのファイルに書き込まれます。もちろん、このファイルがすでに存在する場合、つまり前のプロセスが終了していない場合は、 Nginx は再起動しないので、flock を使用してプロセスが存在するかどうかを検出することもできます。

flock は、ファイル全体に対する勧告的なロックです。言い換えれば、プロセスがファイル (inode) にロックを設定すると、他のプロセスはそれを知ることができます (勧告ロックはプロセスの遵守を強制しません)。最も優れた点は、最初のパラメータがファイル記述子であり、このファイル記述子が閉じられるとロックが自動的に解放されることです。プロセスが終了すると、すべてのファイル記述子が閉じられます。多くの場合、アトミック ロックの解除などを考慮する必要はありません。

詳しく紹介する前に、まずコードを紹介しましょう

package main
import (
    "fmt"
    "os"
    "sync"
    "syscall"
    "time"
)
//文件锁
type FileLock struct {
    dir string
    f   *os.File
}
func New(dir string) *FileLock {
    return &FileLock{
        dir: dir,
    }
}
//加锁
func (l *FileLock) Lock() error {
    f, err := os.Open(l.dir)
    if err != nil {
        return err
    }
    l.f = f
    err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
    if err != nil {
        return fmt.Errorf("cannot flock directory %s - %s", l.dir, err)
    }
    return nil
}
//释放锁
func (l *FileLock) Unlock() error {
    defer l.f.Close()
    return syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
}
func main() {
    test_file_path, _ := os.Getwd()
    locked_file := test_file_path
    wg := sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(num int) {
            flock := New(locked_file)
            err := flock.Lock()
            if err != nil {
                wg.Done()
                fmt.Println(err.Error())
                return
            }
            fmt.Printf("output : %d\n", num)
            wg.Done()
        }(i)
    }
    wg.Wait()
    time.Sleep(2 * time.Second)
}

Windows システムで上記のコードを実行すると、次のエラーが表示されます:

golangでファイルロックを実装する方法

## これは、Windows システムが pid ロックをサポートしていないためで、上記のプログラムを Linux または Mac システムで通常どおり実行する必要があります。

上記のコードは 10 個の goroutine を同時に開始することを示していますが、プログラムの実行中にファイル ロック (flock) を取得できるのは 1 つの goroutine だけです。他のゴルーチンは、flock の取得に失敗した後に例外情報をスローします。これにより、指定された期間内に 1 つのプロセスのみが同じファイルにアクセスできるようにする効果が得られます。

コード内のファイル ロックの具体的な呼び出し:

syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)

syscall.LOCK_EX、syscall.LOCK_NB を使用しますが、これは何を意味しますか?

flock は勧告的なロックであり、必須ではありません。 1 つのプロセスは flock を使用してファイルをロックし、もう 1 つのプロセスはロックされているファイルを直接操作してファイル内のデータを変更できます。その理由は、flock はファイルがロックされているかどうかを検出するためにのみ使用されるためです。 、別のプロセス データを書き込む場合、カーネルはこのプロセスの書き込み操作をブロックしません。これは、勧告ロックのカーネル処理戦略です。

flock には 3 つの主要な操作タイプがあります:

  • LOCK_SH: 共有ロック。複数のプロセスが同じロックを使用でき、読み取り共有ロックとしてよく使用されます。

  • LOCK_EX: 排他ロック。同時に 1 つのプロセスのみが使用を許可され、書き込みロックとしてよく使用されます。

  • LOCK_UN: ロックを解放します。 。

プロセスが flock を使用してファイルをロックしようとしたとき、ファイルがすでに別のプロセスによってロックされている場合、プロセスはロックが解放されるか、LOCK_NB パラメータが設定されるまでブロックされます。 flockを呼び出すときに使用されます。ファイルをロックしようとすると、別のサービスによってロックされていることがわかり、エラー コード EWOULDBLOCK でエラーが返されます。

Flock ロックの解放は非常に独特です。LOCK_UN パラメータを呼び出してファイル ロックを解放することも、fd (flock の最初のパラメータは fd) を閉じることでファイル ロックを解放することもできます。プロセスが終了すると自動的に解放されます。

プログラミング関連の知識について詳しくは、

プログラミング ビデオをご覧ください。 !

以上がgolangでファイルロックを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。