package main import ( "sync" ) func main() { var jagged [][]int jagged = make([][]int, 10) var wg sync.WaitGroup var mu sync.Mutex for i := 0; i < 10; i++ { wg.Add(1) go func(row int) { defer wg.Done() mu.Lock() jagged[row] = append(jagged[row], row*2) // 并发写需加锁 mu.Unlock() }(i) } wg.Wait() }
上述代码通过互斥锁mu保护对交错数组的写操作,避免了并发修改导致的内存损坏。
常见错误模式
直接在 goroutine 中无锁地调用append扩展行切片
误以为各行独立就无需同步,忽略底层数组的动态扩容
使用sync.Map存储行引用却未保护元素级访问
安全实践建议
场景
推荐方案
频繁写入
使用sync.RWMutex或行级锁
只读共享
初始化后冻结结构,避免运行时修改
动态扩展
预分配足够容量或使用通道协调增长
graph TD A[启动协程] --> B{是否共享写?} B -->|是| C[加锁] B -->|否| D[直接访问] C --> E[执行append/修改] D --> F[返回结果]
var data = make([]int, 100) var wg sync.WaitGroup func writer(id int) { defer wg.Done() for i := 0; i < 1000; i++ { index := rand.Intn(100) data[index] = id * 1000 + i // 潜在的写冲突 } } func reader(id int) { defer wg.Done() for i := 0; i < 500; i++ { index := rand.Intn(100) _ = data[index] // 可能读到中间状态 } }
var data [10]int var wg sync.WaitGroup for i := 0; i < 20; i++ { // 越界写入! wg.Add(1) go func(idx int) { defer wg.Done() if idx < len(data) { data[idx] = idx * 2 } }(i) }
public class SafeArray { private int[] data = new int[10]; public synchronized void set(int index, int value) { data[index] = value; } public synchronized int get(int index) { return data[index]; } }
public final class ImmutableCounter { private final int value; public ImmutableCounter(int value) { this.value = value; } public ImmutableCounter increment() { return new ImmutableCounter(this.value + 1); } public int getValue() { return this.value; } }
public class Counter { private volatile int value = 0; public void increment() { value++; // 非原子操作,但volatile保证可见性 } public int getValue() { return value; } }
终极解决方案SMAPI:星露谷物语模组加载器的完全实战指南 【免费下载链接】SMAPI The modding API for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/smap/SMAPI
还在为《星露谷物语》模组管理而烦恼吗?游戏崩溃、模组冲突、加载失败…