Golang中如何实现函数锁定功能

Golang中如何实现函数锁定功能 请查看以上代码,我是否需要将digits函数放在互斥锁中,因为变量number在这些goroutine之间是共享的。

func main() {
	var number int
	var wg sync.WaitGroup
	var mutex sync.Mutex

	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			mutex.Lock()
			number = rand.Intn(100)
			fmt.Printf("Number: %d\n", number)
			digits(number)
			mutex.Unlock()
		}()
	}

	wg.Wait()
}

func digits(number int) {
	var ds []int
	for number > 0 {
		ds = append(ds, number%10)
		number = number / 10
	}
	fmt.Printf("Digits: %v\n", ds)
}

更多关于Golang中如何实现函数锁定功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

感谢回复…这是否意味着,在通道中它永远不会发生冲突。

更多关于Golang中如何实现函数锁定功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢回复……这是否意味着,在通道中永远不会发生冲突?

如果没有你的"并发"计划/映射,不能100%断定它永远不会发生冲突。

然而我们可以100%确定的是,通道用于进程间的异步消息传递,其功能与互斥锁略有不同。所以在你的情况下,由于没有任何共享变量,只是在这里和那里传递输出,通道是最佳选择。

不,不需要。

因为您对 calcSquarescalcCubes 都使用了通道和委托机制。每当它们中的任何一个异步调用 digits 时,它们都有一个清晰且专用的通道来回复。此外,在这种情况下,使用通道比互斥锁更合理。做得好。


只有当多个进程读取或写入共享变量时,才需要使用互斥锁。例如,Go 的 map 不是线程安全的,因此如果有多个进程对同一个 map 对象进行读写操作,使用互斥锁比使用通道来同步 map 对象更合理。

在您提供的代码中,number 变量确实在多个 goroutine 之间共享,并且存在竞态条件。当前实现中,您将互斥锁应用于整个 goroutine 函数体,包括对 digits 函数的调用。然而,digits 函数本身是线程安全的,因为它只操作其参数 number 的副本,不访问共享状态。

以下是优化后的代码示例,将锁的范围缩小到仅保护共享变量 number 的读写:

package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func main() {
	var number int
	var wg sync.WaitGroup
	var mutex sync.Mutex

	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			
			// 只锁定对共享变量 number 的读写
			mutex.Lock()
			number = rand.Intn(100)
			localNumber := number // 创建局部副本
			mutex.Unlock()
			
			fmt.Printf("Number: %d\n", localNumber)
			digits(localNumber) // 使用局部副本,无需锁保护
		}()
	}

	wg.Wait()
}

func digits(number int) {
	var ds []int
	n := number // 保留原始值,避免修改参数
	for n > 0 {
		ds = append(ds, n%10)
		n = n / 10
	}
	fmt.Printf("Digits: %v\n", ds)
}

关键改进点:

  1. 锁只保护对共享变量 number 的赋值操作
  2. 创建局部变量 localNumber 来保存 number 的当前值,这样 digits 函数可以无锁运行
  3. digits 函数内部使用局部变量 n 进行操作,避免修改函数参数

这种实现减少了锁的持有时间,提高了并发性能,同时仍然保证了数据竞争的安全性。

回到顶部