GO并发编程【】

GO并发编程

1. Mutex包的功能和用法。(Mutex的4种状态,正常模式和饥饿模式,自旋)

互斥锁Mutex:
Mutex 用于提供一种加锁机制(Locking Mechanism),
保证同一时刻只有一个goroutine在临界区运行。


    var mutex sync.Mutex
    mutex.Lock()
    ...
    mutex.Unlock()

type Mutex struct {
    state int32 // 表示当前互斥锁的状态  
        // 互斥锁上等待的 Goroutine 个数|互斥锁进入饥饿状态|从正常模式被从唤醒|互斥锁的锁定状态
    sema  uint32 // 控制锁状态的信号量
}

自旋:加锁时,如果当前Locked位为1,说明该锁当前由其他协程持有,尝试加锁的协程并不是马上转入阻塞,而是会持续的探测Locked位是否变为0,这个过程即为自旋过程。
自旋条件:
1.自旋次数要足够小,通常为4,即自旋最多4
2.CPU核数要大于1,否则自旋没有意义,因为此时不可能有其他协程释放锁
3.协程调度机制中的Process数量要大于1,比如使用GOMAXPROCS()将处理器设置为1就不能启用自旋
4.协程调度机制中的可运行队列必须为空,否则会延迟协程调度
自旋的优势:
自旋的优势是更充分的利用CPU,尽量避免协程切换。
Mutex的三种状态:
正常模式:锁的等待者会按照先进先出的顺序获取锁
饥饿模式:刚被唤起的 Goroutine 与新创建的 Goroutine 竞争时,大概率会获取不到锁,一旦 Goroutine 超过 1ms 没有获取到锁,它就会将当前互斥锁切换饥饿模式
Woken状态: 用于加锁和解锁过程的通信,同一时刻,两个协程一个在加锁,一个在解锁,在加锁的协程可能在自旋过程中,此时把Woken标记为1,用于通知解锁协程不必释放信号量了,好比在说:你只管解锁好了,不必释放信号量,我马上就拿到锁了。

2. RWMutex的功能实现和使用时的注意事项。

它允许多个读操作同时进行,但只允许一个写操作进行。
读写锁RWMutex: 场景: 缓存写入


    func (*RWMutex) Lock //方法将rw锁定为写入状态,禁止其他线程读取或者写入。
    func (*RWMutex) Unlock //方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。
    func (*RWMutex) RLock //方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。
    func (*RWMutex) RUnlock //方法解除rw的读取锁状态,如果m未加读取锁会导致运行时错误。

注意:
对于写操作,要保证加锁和解锁的配对。
对于读操作,读锁和读解锁的数量要对应。

3. Broadcast 和 single 的区别。

Broadcast:即广播模式,表示向所有的节点发送消息,不需要保证消息的顺序。
Single:即单播模式,表示向单个节点发送消息,通常需要保证消息的顺序,在单播模式中消息一般是在两个节点之间进行传递。
广播模式一般用于系统状态的同步,单播模式一般用于点对点通信。

4. waitGroup的用法和实现原理。

WaitGroup是Go语言中的同步机制,它可以用来等待一个或多个Goroutine执行结束。


func main(){
   var wg sync.WaitGroup
   var urls = []string{
      "http://www.golang.org/",
      "http://www.google.com/",
      "http://www.somestupidname.com/",
   }
   for _, url := range urls {
      wg.Add(1)
      go func(url string) {
         defer wg.Done()
         fmt.Println(url)
      }(url)
   }
   wg.Wait()
}

它实现原理是一个计数器,通过Add方法将计数器增加,通过Done方法将计数器减少,通过Wait方法阻塞主Goroutine,知道计数器减少为0,表示所有Goroutine执行结束。

使用WaitGroup时需要注意以下事项:
1. Add和Done方法一定要配对使用,一个Add对应一个Done。
2. 在Wait方法调用前一定要调用Add方法。

5. 原子操作是什么,怎么实现,和锁的区别,CAS是什么。

原子操作是指一个或多个操作,其在计算机中是不可分割的,不可中断的。它们通常是实现并发编程时的基本操作,以保证数据的正确性和完整性。

CAS(Compare and Swap)是一种在原子操作中使用的技术,用于确保只有当指定的内存位置上的值与预期值相等时,才对该内存位置进行更新。这种技术在实现原子操作时非常有用,因为它们允许您在并发环境中安全地更新数据。

实现原理:原子操作通常是通过操作系统或硬件的特殊功能实现的,以确保在一次访问过程中不会被打断或改变。

与锁的区别:锁用于对代码段进行同步,以防止多个线程同时访问代码。然而,原子操作更加简单,速度更快,因为它们不需要涉及内存锁定和线程同步的复杂性。

6. Sync包的功能和用法。主要是 Once 和Pool 的实现原理和具体用法。

sync包提供了并发编程控制锁、go的同步机制、并发安全的map
sync.Once”是一种类型,它只表示对其基础函数的一次调用。无论并行执行的goroutine有多少,确保昂贵的设置只执行一次非常有用。
sync.Pool”是一种提供临时对象池的类型。在创建和释放大量临时对象的情况下,使用池可以帮助减少内存分配、垃圾收集压力并提高性能。池类型自动跟踪未使用的对象,并回收它们以供以后使用。

打赏 赞(0) 分享'
分享到...
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

文章目录