GolangNote

Golang笔记

golang共享数据用Mutex 或 Channel

Permalink

在go 里,多线程对共享数据的操作一般要使用Mutex 或 Channel 来加锁或隔离通信。下面是一个使用Mutex 和 Channel 比较的例子。

golang共享数据用Mutex 或 Channel

Go: Mutex/Channel共享数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

var m map[string]string

type Data struct {
	Key   string
	Value string
}

func worker(queue chan Data, finished chan struct{}) {

	for {
		d, more := <-queue
		if !more {
			fmt.Println("Stopping worker due to closed channel")
			break

		}
		//fmt.Print(".")
		m[d.Key] = d.Value
	}
	finished <- struct{}{}
}

func main() {
	ConcurrentSender := 100

	m = make(map[string]string)
	done := []chan struct{}{}
	mutex := sync.Mutex{}
	start := time.Now()

	for i := 0; i < ConcurrentSender; i++ {
		d := make(chan struct{})
		done = append(done, d)
		go func(done chan struct{}, mut *sync.Mutex, ind int) {
			for j := 0; j < 100; j++ {
				mut.Lock()
				m[strconv.Itoa(j)] = strconv.Itoa(j + (1000 * (ind + 1)))
				mut.Unlock()
			}
			done <- struct{}{}
		}(d, &mutex, i)
	}
	for _, d := range done {
		_ = <-d
	}

	duration := time.Since(start)

	fmt.Printf("\nMutex Solution took %s", duration)

	m = make(map[string]string)

	done = []chan struct{}{}

	queue := make(chan Data)
	// start of the worker go routine
	finished := make(chan struct{})
	go worker(queue, finished)

	start = time.Now()
	for i := 0; i < ConcurrentSender; i++ {
		d := make(chan struct{})
		done = append(done, d)
		go func(queue chan Data, done chan struct{}, ind int) {
			for i := 0; i < 100; i++ {
				// Write element to queue
				queue <- Data{Key: strconv.Itoa(i), Value: strconv.Itoa(i + (100 * (ind + 1)))}
			}
			done <- struct{}{}
		}(queue, d, i)

	}

	for _, d := range done {
		_ = <-d
	}

	duration = time.Since(start)

	close(queue)
	_ = <-finished
	fmt.Printf("Channel Solution took %s", duration)

}

从复杂度和开销来说 Channel 要比 Mutex 昂贵。虽然官方说:

"Don't communicate by sharing memory; instead, share memory by communicating." (“不要通过共享内存进行通信,而是通过通信共享内存。”)

但实际要看场合,简单的、要求实时性比较高的还是使用 Mutex 方便。

Related articles

Golang 把cookie 字符串解析为cookie 结构

在做爬虫时有时候会遇到需要带已登录的 cookie 请求,这个时候最简单的方法是在浏览器登录后,在开发者面板找到cookie 字符串,然后拷贝粘贴。这就面临一个问题需要把cookie 字符串解析成Go 语言 cookie 结构体。...

Golang phantomjs 动态代理实现

phantomjs 是个很优秀的软件,虽然现在被chrome headless 抢了风头,但在某些特定场合,使用phantomjs 还是很方便,这里是介绍使用Go 实现动态代理。...

Write a Comment to "golang共享数据用Mutex 或 Channel"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.16.5 Processed in 1ms