Heim  >  Artikel  >  Backend-Entwicklung  >  So implementieren Sie eine Dateisperre in Golang

So implementieren Sie eine Dateisperre in Golang

青灯夜游
青灯夜游Original
2022-12-19 11:03:064991Durchsuche

In Golang können Sie die API des Synchronisierungspakets verwenden, um die Dateisperre zu implementieren. Die Dateisperre (Flock) ist eine Empfehlungssperre für die gesamte Datei. Das heißt, wenn ein Prozess eine Sperre für eine Datei (Inode) anordnet, können andere Prozesse davon erfahren (Beratungssperren erzwingen nicht die Einhaltung der Dateisperren). Die Syntax lautet „syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)“.

So implementieren Sie eine Dateisperre in Golang

Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.

Wenn wir einige Programme mit der Go-Sprache entwickeln, kommt es häufig vor, dass mehrere Prozesse gleichzeitig dieselbe Datei bearbeiten, was leicht zu einer Verwechslung der Daten in der Datei führen kann. Zu diesem Zeitpunkt müssen wir einige Mittel einsetzen, um diese Konflikte auszugleichen, und die Dateisperre (Herde) ist entstanden. Lassen Sie uns sie unten vorstellen.

Für Flock ist das häufigste Beispiel Nginx. Nach der Ausführung des Prozesses wird die aktuelle PID in diese Datei geschrieben. Wenn diese Datei bereits vorhanden ist, dh der vorherige Prozess nicht beendet wurde, wird dies bei Nginx nicht der Fall sein Neustart, daher kann Flock auch verwendet werden, um zu erkennen, ob ein Prozess vorhanden ist.

flock ist eine Empfehlungssperre für die gesamte Datei. Mit anderen Worten: Wenn ein Prozess eine Sperre für eine Datei (Inode) verhängt, können andere Prozesse davon erfahren (beratende Sperren zwingen Prozesse nicht zur Einhaltung). Das Beste daran ist, dass sein erster Parameter ein Dateideskriptor ist und die Sperre automatisch aufgehoben wird, wenn der Dateideskriptor geschlossen wird. Wenn der Prozess beendet wird, werden alle Dateideskriptoren geschlossen. So oft besteht keine Notwendigkeit, an Dinge wie das Entsperren von Atomschlössern zu denken.

Bevor wir die Details vorstellen, stellen wir zuerst den Code vor

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)
}

Wenn der obige Code unter einem Windows-System ausgeführt wird, wird die folgende Fehlermeldung angezeigt:

So implementieren Sie eine Dateisperre in Golang

Dies liegt daran, dass das Windows-System die PID-Sperre nicht unterstützt, daher müssen wir dies tun Führen Sie es auf einem Linux- oder Mac-System aus, um das obige Programm normal auszuführen.

Der obige Code zeigt das gleichzeitige Starten von 10 Goroutinen, aber während der Ausführung des Programms kann nur eine Goroutine die Dateisperre (Flock) erhalten. Andere Goroutinen geben Ausnahmeinformationen aus, nachdem sie den Flock nicht erhalten haben. Dadurch kann erreicht werden, dass innerhalb eines bestimmten Zeitraums nur ein Prozess auf dieselbe Datei zugreifen darf.

Der spezifische Aufruf der Dateisperre im Code:

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

Wir haben syscall.LOCK_EX, syscall.LOCK_NB verwendet. Was bedeutet das?

flock ist eine empfohlene Sperre und nicht zwingend erforderlich. Ein Prozess verwendet Flock, um die Datei zu sperren, und der andere Prozess kann die gesperrte Datei direkt bearbeiten und die Daten in der Datei ändern. Der Grund dafür ist, dass Flock nur verwendet wird, um zu erkennen, ob die Datei bereits gesperrt ist. Ein anderer Prozess Beim Schreiben von Daten blockiert der Kernel den Schreibvorgang dieses Prozesses nicht. Dies ist die Kernel-Verarbeitungsstrategie der Beratungssperre.

flock verfügt über drei Hauptoperationstypen:

  • LOCK_SH: Gemeinsame Sperre, mehrere Prozesse können dieselbe Sperre verwenden, häufig als gemeinsame Lesesperre verwendet;

  • LOCK_EX: Exklusive Sperre, die nur von einem Prozess verwendet werden darf es wird gleichzeitig oft als Schreibsperre verwendet

  • LOCK_UN: Sperre aufheben.

Wenn ein Prozess Flock verwendet, um zu versuchen, eine Datei zu sperren und die Datei bereits von einem anderen Prozess gesperrt ist, wird der Prozess blockiert, bis die Sperre aufgehoben wird oder der Parameter LOCK_NB beim Aufruf von Flock verwendet wird. Beim Versuch, die Datei zu sperren, wird festgestellt, dass sie von einem anderen Dienst gesperrt wurde, und es wird ein Fehler mit dem Fehlercode EWOULDBLOCK zurückgegeben.

Die Freigabe der Flock-Sperre ist sehr einzigartig. Sie können den Parameter LOCK_UN aufrufen, um die Dateisperre aufzuheben, oder Sie können die Dateisperre aufheben, indem Sie fd schließen (der erste Parameter von flock ist fd), was bedeutet, dass flock dem Prozess folgt. wird beim Schließen automatisch freigegeben.

Weitere Kenntnisse zum Thema Programmierung finden Sie unter: Programmiervideos! !

Das obige ist der detaillierte Inhalt vonSo implementieren Sie eine Dateisperre in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn