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("ディレクトリ%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("出力:%d\n"、num)
wg.Done()
}(i)
}
wg.Wait()
time.Sleep(2*time.Second)
}
Windows で上記のコードを実行すると、次のエラーが発生します。
undefined: syscall.Flock
undefined: syscall.LOCK_EX
undefined: syscall.LOCK_NB
undefined: syscall.Flock
undefined: syscall.LOCK_UN
これは、Windows システムが PID ロックをサポートしていないためで、上記のプログラムを Linux または Mac システムで通常どおり実行する必要があります。
上記のコードは、10 個のゴルーチンが同時に開始されることを示していますが、プログラムの実行中にファイル ロック (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 を使用してファイルをロックし、別のプロセスはロックされたファイルを直接操作してファイル内のデータを変更できます。その理由は、flock はファイルがロックされているかどうかを検出するためにのみ使用されるためです。ロックされているファイルについては、別のプロセス データを書き込む場合、カーネルはこのプロセスの書き込み操作を妨げません。これは、勧告ロックのカーネル処理戦略です。
flock には主に 3 種類の操作があります。
- LOCK_SH: 共有ロック。複数のプロセスが同じロックを使用でき、読み取り共有ロックとしてよく使用されます。
- LOCK_EX: 排他的ロック。同時に 1 つのプロセスのみが使用を許可され、書き込みロックとしてよく使用されます。
- LOCK_UN: ロックを解除します。
プロセスが flock を使用してファイルをロックしようとしたとき、そのファイルが別のプロセスによってすでにロックされている場合、プロセスはロックが解放されるまで、または LOCK_NB パラメーターを使用して flock が呼び出されるまでブロックされます。ファイルをロックしようとすると、他のサービスによってロックされていることがわかり、エラー コード EWOULDBLOCK でエラーが返されます。
flock ロックの解放は非常に特徴的で、LOCK_UN パラメータを呼び出してファイル ロックを解放することも、fd (flock の最初のパラメータは fd) を閉じることでファイル ロックを解放することもできます。プロセスが閉じられ、自動的に解放されます。