Mutex正常模式与饥饿模式

简介: 在Go中,sync包提供了一种称为Mutex(互斥锁)的机制来实现对共享资源的并发访问控制。Mutex有两种模式:正常模式和饥饿模式。

正常模式是指当有多个goroutine同时请求锁时,Mutex会公平地选择一个goroutine来获取锁,其他goroutine会被放入一个FIFO(先进先出)的等待队列中。当锁被释放时,等待队列中的goroutine会按照先后顺序获取锁。

饥饿模式是指当有多个goroutine同时请求锁时,Mutex不公平地选择一个goroutine来获取锁,而是优先选择之前请求锁但被拒绝的goroutine,而不是等待队列中的其他goroutine。这样,被拒绝的goroutine有机会尽快获取锁,避免了其他goroutine持有锁的时间过长而导致的不公平性。

通过调用Mutex的方法Lock()和Unlock()来获取和释放锁。示例如下:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
   
    var mu sync.Mutex

    for i := 0; i < 10; i++ {
   
        go func() {
   
            mu.Lock()
            defer mu.Unlock()

            fmt.Println("goroutine", i, "got the lock")
            time.Sleep(time.Second)
            fmt.Println("goroutine", i, "released the lock")
        }()
    }

    time.Sleep(5 * time.Second)
}

上面的示例中,我们创建了10个并发的goroutine,每个goroutine都会获取锁后打印一条消息,然后休眠1秒,最后释放锁。程序运行后,我们会看到goroutine的顺序是乱序的,这是因为Mutex是无序的,没有固定的顺序。

如果我们将Mutex的模式从正常模式更改为饥饿模式,可以通过修改Mutex的配置来实现。例如:

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)

type starvingMutex struct {
   
    sync.Mutex
}

func (m *starvingMutex) Lock() {
   
    atomic.StoreInt32((*int32)(&m.Mutex), 1)
    m.Mutex.Lock()
}

func (m *starvingMutex) Unlock() {
   
    m.Mutex.Unlock()
    atomic.StoreInt32((*int32)(&m.Mutex), 0)
}

func main() {
   
    var mu starvingMutex

    for i := 0; i < 10; i++ {
   
        go func() {
   
            mu.Lock()
            defer mu.Unlock()

            fmt.Println("goroutine", i, "got the lock")
            time.Sleep(time.Second)
            fmt.Println("goroutine", i, "released the lock")
        }()
    }

    time.Sleep(5 * time.Second)
}

上面的示例中,我们自定义了一个starvingMutex类型,内嵌了sync.Mutex,并重写了Lock()和Unlock()方法。在Lock()方法中,我们先通过atomic.StoreInt32方法将Mutex的状态设置为1,然后再调用Mutex的Lock()方法。这样,之前请求锁但被拒绝的goroutine就有机会尽快获取锁。

注意,饥饿模式可能会导致更多的锁竞争和额外的性能开销,因此在大多数情况下,默认使用正常模式即可。只有在特定场景下才考虑切换到饥饿模式。

目录
相关文章
|
5月前
|
安全 算法 Linux
Linux多线程【线程互斥与同步】
Linux多线程【线程互斥与同步】
47 0
|
5月前
|
Linux 数据安全/隐私保护
Linux线程同步(条件变量)
Linux线程同步(条件变量)
38 0
|
7月前
StampedLock 支持的三种锁模式
StampedLock 支持的三种锁模式
23 1
|
12月前
并发编程-17AQS同步组件之 Semaphore 控制并发线程数的信号量
并发编程-17AQS同步组件之 Semaphore 控制并发线程数的信号量
43 0
|
安全 Linux 数据安全/隐私保护
Linux线程同步与互斥(一)
着重讲解Linux线程的互斥!
Linux线程同步与互斥(一)
|
Linux API
【Linux线程同步专题】二、读写锁
【Linux线程同步专题】二、读写锁
158 0
|
Linux
【Linux线程同步专题】三、条件变量
【Linux线程同步专题】三、条件变量
106 0
|
API C# Windows
C#多线程(4):进程同步Mutex类
C#多线程(4):进程同步Mutex类
216 0
C#多线程(4):进程同步Mutex类
|
安全 C# 数据安全/隐私保护
C#(四十三)之线程Mutex互斥
Mutex(互斥体): 排他性的使用共享资源称为线程间的互斥。 使用Mutex类要比使用monitor类消耗更多的系统资源,但他可以跨越多个应用程序,在多个应用程序间同步。
177 0
C#(四十三)之线程Mutex互斥