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就有机会尽快获取锁。

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

目录
相关文章
|
2天前
|
安全 算法 Linux
Linux多线程【线程互斥与同步】
Linux多线程【线程互斥与同步】
48 0
|
2天前
|
Linux 数据安全/隐私保护
Linux线程同步(条件变量)
Linux线程同步(条件变量)
38 0
|
2天前
|
Linux
Linux线程同步(try锁和读写锁)
Linux线程同步(try锁和读写锁)
34 0
|
12月前
并发编程-17AQS同步组件之 Semaphore 控制并发线程数的信号量
并发编程-17AQS同步组件之 Semaphore 控制并发线程数的信号量
44 0
|
安全 Linux 数据安全/隐私保护
Linux线程同步与互斥(一)
着重讲解Linux线程的互斥!
Linux线程同步与互斥(一)
|
Linux API
【Linux线程同步专题】二、读写锁
【Linux线程同步专题】二、读写锁
158 0
|
Linux
【Linux线程同步专题】三、条件变量
【Linux线程同步专题】三、条件变量
107 0
|
Linux 调度 数据库
【Linux线程同步专题】一、什么是线程同步、互斥量与死锁
【Linux线程同步专题】一、什么是线程同步、互斥量与死锁
122 0
|
网络协议 数据建模 测试技术
全局互斥解锁资源竞争 | 学习笔记
快速学习全局互斥解锁资源竞争
84 0
全局互斥解锁资源竞争 | 学习笔记
|
安全 调度 数据库
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
498 0

热门文章

最新文章

相关实验场景

更多