38-mutexes

// 对于简单的计数器状态可以通过 atomic 操作来控制
// 对于更复杂的状态,可以使用互斥锁(mutex)安全地访问多个goroutine中的数据

package main

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

func main() {
	var state = make(map[int]int) // 创建一个map表示状态(state)

	var mutex = &sync.Mutex{} // 互斥锁会同步对状态的访问

	// 用于追踪读写的操作数量
	var readOps uint64
	var writeOps uint64

	for r := 0; r < 100; r++ { // 启动100个goroutine,执行针对状态的重复读取
		go func() {
			total := 0
			for {
				key := rand.Intn(5)           // 对于每次读取,生成一个访问key
				mutex.Lock()                  // 锁定互斥锁,以确保对状态的独占访问
				total += state[key]           // 从map中读取所选key对应的值
				mutex.Unlock()                // 释放互斥锁
				atomic.AddUint64(&readOps, 1) // 增加readOps计数
				time.Sleep(time.Millisecond)  // 每个goroutine每毫秒执行一次操作
			}
		}()
	}

	for w := 0; w < 10; w++ { // 启动10个goroutine来模拟写入操作,处理模式与读取操作相同
		go func() {
			for {
				key := rand.Intn(5)
				val := rand.Intn(100)
				mutex.Lock()
				state[key] = val
				mutex.Unlock()
				atomic.AddUint64(&writeOps, 1)
				time.Sleep(time.Millisecond)
			}
		}()
	}

	time.Sleep(time.Second) // 等待上述读写操作工作1秒钟

	// 获取1秒内的读取和写入的操作次数
	readOpsFinal := atomic.LoadUint64(&readOps)
	fmt.Println("readOps:", readOpsFinal)
	writeOpsFinal := atomic.LoadUint64(&writeOps)
	fmt.Println("writeOps:", writeOpsFinal)

	// 锁定状态并输出状态中的值
	mutex.Lock()
	fmt.Println("state:", state)
	mutex.Unlock()
}

//  运行结果表面针对互斥同步状态在一秒内大概执行了9万次操作
上次修改: 10 January 2020