目录

golang interview

hhhhh

一个月学习计划

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
第一周

在gpt里面

hugo代办:
把文档看看,知道怎么写文档
平时整理一下面试题弄出来,自己制作成这样的网页
在后台一直运行hugo,这样的话会自动渲染

能不能调用gpt的接口,把问过的问题全部放到hugo里面渲染啊?只需要改hugo的文件就行了呀

代码计划:
有几个代码要写的


spin-lock

Spinlock(自旋锁)详解

1. 基本概念

Spinlock(自旋锁)是一种 忙等待(Busy-Waiting)锁,当线程尝试获取锁时,如果锁已被占用,线程不会进入睡眠状态,而是持续循环检查锁的状态,直到锁被释放。

2. 工作原理

  • 获取锁:线程通过原子操作(如 CAS, Compare-And-Swap)尝试获取锁。
  • 锁被占用:如果锁已被占用,线程会在一个循环中不断检查锁是否可用(自旋)。
  • 锁释放:持有锁的线程释放锁后,等待的线程立即获取锁并继续执行。

伪代码示例(CAS 实现)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type SpinLock struct {
    locked int32 // 0=unlocked, 1=locked
}

func (s *SpinLock) Lock() {
    for !atomic.CompareAndSwapInt32(&s.locked, 0, 1) {
        // 自旋等待(CPU 空转)
    }
}

func (s *SpinLock) Unlock() {
    atomic.StoreInt32(&s.locked, 0)
}

3. 特点

特点 说明
不放弃 CPU 线程不会进入睡眠状态,而是占用 CPU 循环等待。
低延迟 锁释放后能立即获取,无线程唤醒开销(适合短临界区)。
高 CPU 占用 自旋时会空转 CPU,可能浪费资源(长时间等待不适用)。
无调度介入 不涉及内核态切换,纯用户态操作(对比互斥锁需要 OS 介入)。

4. 适用场景

  • 短临界区:锁持有时间极短(如几个 CPU 周期)。
    • 例如:内核中断处理、无竞争场景下的快速路径(fast-path)。
  • 多核 CPU:单核 CPU 上自旋无意义(会占用唯一 CPU)。
  • 避免上下文切换:对延迟敏感的场景(如高性能计算、内核同步)。

5. 不适用场景

  • 长临界区:自旋会浪费 CPU 时间,应改用阻塞锁(如 mutex)。
  • 单核 CPU:自旋会阻止锁持有者运行,导致死锁。

6. 改进变种

  • 自适应自旋锁(Adaptive Spinlock)
    根据历史等待时间动态选择自旋或阻塞(如 Java 的 synchronized)。
  • Ticket Spinlock
    按请求顺序分配锁,避免饥饿(如 Linux 内核的 ticket_spinlock)。

7. 代码示例(Go 实现)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import "sync/atomic"

type SpinLock struct {
    lock int32
}

func (s *SpinLock) Lock() {
    for !atomic.CompareAndSwapInt32(&s.lock, 0, 1) {
        // 可插入 runtime.Gosched() 减少 CPU 占用(但影响性能)
    }
}

func (s *SpinLock) Unlock() {
    atomic.StoreInt32(&s.lock, 0)
}

// 使用示例
var sl SpinLock
sl.Lock()
defer sl.Unlock()
// 临界区代码

8. 与互斥锁(Mutex)对比

特性 Spinlock Mutex
等待方式 忙等待(CPU 空转) 阻塞(线程休眠)
开销 低(无上下文切换) 高(需 OS 调度)
适用场景 短临界区、多核 长临界区、单核/多核
实现级别 用户态 内核态介入

9. 注意事项

  • CPU 浪费:长时间自旋会显著增加 CPU 使用率。
  • 优先级反转:低优先级线程持有锁时,高优先级线程自旋可能导致死锁。
  • Go 的特殊性:Go 的 runtime 对自旋有优化(如混合自旋+阻塞的 sync.Mutex)。

10. 经典应用

  • Linux 内核:短临界区同步(如中断处理)。
  • 并发数据结构:无锁(lock-free)算法的后备方案。
  • 高性能计算:避免线程休眠的开销(如内存分配器)。

如果需要进一步探讨(如与 futex 的结合、性能测试等),可以继续深入!