golang 线程锁

发布时间:2024-11-21 23:31:27

Go语言是一门由谷歌公司开发的编程语言,它专门为构建高效、可靠的软件而设计。其中一个Go语言的特性是其并发编程模型,它使用了轻量级线程(goroutine)和通信顺序进程(CSP)风格的类似于管道的通信机制。然而,并发编程中常常伴随着共享变量的访问和修改,为了确保数据的一致性,我们需要引入线程锁。下面本文将着重介绍如何在Go语言中使用线程锁。

互斥锁(Mutex)

互斥锁是Go语言提供的最简单的锁类型,它只有两个方法Lock和Unlock。当某个goroutine获取了互斥锁后,其他goroutine就无法再获取这个锁,只能等待该锁被释放。下面是一个使用互斥锁的例子:

import (
    "sync"
)

var count = 0
var lock sync.Mutex

func increment() {
    lock.Lock()
    count++
    lock.Unlock()
}

func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            increment()
        }()
    }
    wg.Wait()
    fmt.Println(count)
}

读写锁(RWMutex)

互斥锁的特点是同一时间只允许一个goroutine获取锁,而读写锁则允许多个读操作同时进行,但只有一个写操作可以进行。这在某些场景下可以提高并发性能。下面是一个使用读写锁的例子:

import (
    "sync"
)

var count = 0
var rwLock sync.RWMutex

func read() {
    rwLock.RLock()
    defer rwLock.RUnlock()
    fmt.Println(count)
}

func write() {
    rwLock.Lock()
    defer rwLock.Unlock()
    count++
}

func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            read()
            write()
        }()
    }
    wg.Wait()
}

条件变量(Cond)

除了互斥锁和读写锁,Go语言还提供了条件变量用于在多个goroutine之间进行等待和唤醒的操作。条件变量需要搭配互斥锁一起使用,下面是一个使用条件变量的例子:

import (
    "sync"
    "time"
)

var count = 0
var cond = sync.NewCond(&sync.Mutex{})

func waiting() {
    cond.L.Lock()
    defer cond.L.Unlock()
    for count < 5 {
        cond.Wait()
    }
    fmt.Println("count reached 5")
}

func increment() {
    cond.L.Lock()
    defer cond.L.Unlock()
    count++
    if count == 5 {
        cond.Broadcast()
    }
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func() {
        defer wg.Done()
        waiting()
    }()
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            increment()
            time.Sleep(time.Second)
        }
    }()
    wg.Wait()
}

通过以上的介绍,我们了解了Go语言中三种常见的线程锁类型:互斥锁、读写锁和条件变量。在实际开发中,我们可以根据需求选择不同的锁类型来保护共享资源的访问。线程锁在并发编程中起着至关重要的作用,它确保了多个goroutine之间正确且安全地访问共享资源。

相关推荐