go锁与chan的性能对比

锁的作用

  • 解决并发安全问题,流程控制等

chan 的作用

  • 线程通信(数据传输), 并发安全,流程控制

golang的数据并不是并发安全的

  • golang的变量并不是并发安全的
  • 锁与chan都可以解决并发安全的问题,那么应该如何选择?
go 复制代码
// 锁
func LockServe(lock *sync.Mutex) {
	lock.Lock()
	defer lock.Unlock()
	//todo: 业务逻辑
	//...
}

// channel 读(单线程)
func ChanRead(ch chan struct{}) {
	for {
		<-ch
	}
}

// channel 读(多线程)
func ChanReadMulti(ch chan struct{}) {
	for i := 0; i < 100; i++ {
		go ChanRead(ch)
	}
}

// channel 写
func ChanWrite(ch chan struct{}) {
	ch <- struct{}{}
}


// 读写锁性能(单线程)
func BenchmarkLock(b *testing.B) {
	lock := &sync.Mutex{}
	//开始计时
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		LockServe(lock)
	}
		//BenchmarkLock-8         128537480                9.141 ns/op           0 B/op
}

// 读写锁性能(多线程)
func BenchmarkLockMulti(b *testing.B) {
	lock := &sync.Mutex{}
	//开始计时
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			LockServe(lock)
		}
	})
	//BenchmarkLockMulti-8    15528596                77.23 ns/op            0 B/op
}

// channel 通信(单线程)
func BenchmarkChanRead(b *testing.B) {
	ch := make(chan struct{}, 9)
	defer close(ch)
	go ChanRead(ch)
	//开始计时
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ChanWrite(ch)
	}
	//BenchmarkChanRead-8     21222759                55.43 ns/op            0 B/op
}

// channel 通信(多线程读)
func BenchmarkChanReadMulti(b *testing.B) {
	ch := make(chan struct{}, 9)
	defer close(ch)
	go ChanReadMulti(ch)
	//开始计时
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		ChanWrite(ch)
	}
	//BenchmarkChanReadMulti-8         4238251               260.1 ns/op             0
}

// channel 通信(多线程写)
func BenchmarkChanWrite(b *testing.B) {
	ch := make(chan struct{}, 1000)
	defer close(ch)
	go ChanRead(ch)
	//开始计时
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			ChanWrite(ch)
		}
	})
	// BenchmarkChanWrite-8     5177377               299.1 ns/op             0 B/op
}

// channel 通信(多线程读写)
func BenchmarkChanReadWrite(b *testing.B) {
	ch := make(chan struct{}, 1000)
	defer close(ch)
	go ChanReadMulti(ch)
	//开始计时
	b.ResetTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			ChanWrite(ch)
		}
	})
	// BenchmarkChanReadWrite-8          558490              3862 ns/op               0 B/op          0 allocs/op
}

在单线程下:锁 :128537480 qps; chan: 21222759 qps

多线程下: 锁 : 15528596 qps; chan : 5177377 qps

单论性能,锁要比chan更加优秀

为什么锁的性能更加优秀?

  • 锁是原子的操作,消耗更低,性能更高
  • chan的底层有更加复杂的通信逻辑,消耗较大,在多线程情况下相差3倍

如何选择?

  • 在之需要解决并发问题或者流程控制的情况下优先考虑锁,因为性能更高
  • 如果需要线程通信 以及 数据传输使用chan
相关推荐
kfaino6 小时前
码农的AI翻身(三)你好,我叫 Embedding
后端·ai编程
葫芦和十三7 小时前
图解 MongoDB 18|复制集拓扑:Primary、Secondary 和 Arbiter 的分工
后端·mongodb·面试
爱勇宝7 小时前
大多数人不是在使用 AI 赚钱,而是在帮 AI 公司赚钱
前端·后端·程序员
程序员cxuan10 小时前
虽迟但到!GPT-5.6 终于来了!
人工智能·后端·程序员
IT_陈寒12 小时前
React的这个渲染问题连官方文档都没说清楚
前端·人工智能·后端
葫芦和十三13 小时前
图解 MongoDB 15|journal 与持久化:写入怎么不丢,崩溃怎么恢复
后端·mongodb·面试
葫芦和十三13 小时前
图解 MongoDB 16|压缩:snappy、zstd 和 zlib 的取舍
后端·mongodb·面试
苍何13 小时前
终于找到免费开源TTS模型,克隆声音不要钱,本地电脑也能跑
后端
用户5936087414013 小时前
Spring AI 集成 DeepSeek 原生供应商并实现think模式
后端
追逐时光者13 小时前
别再满网找零散工具了,腾讯 QQ 浏览器这个“帮小忙”工具箱真能省时间
前端·后端