go并发编程模式(atomic、互斥锁、正常有并发安全的map、读写锁、同步map、只执行一次的任务)

余生颓废 提交于 2020-08-08 16:02:32

1)目录


|____go.mod
|____atomic
| |____impl
| | |____lockcounter.go
| | |____counter.go
| | |____atomiccounter.go
| | |____nonlockcounter.go
| |____main.go
|____synconce
| |____main.go
|____rwmutex
| |____main.go
|____normalmap
| |____main.go
|____mutex
| |____main.go
|____syncmap
| |____main.go
 


















2)实现
|____go.mod

module github.com/jianan/demo

go 1.13

|____atomic
| |____impl
| | |____lockcounter.go

package impl

import "sync"

type LockCounter struct {
	val  int64
	lock sync.Mutex
}

func (l *LockCounter) Increment() {
	l.lock.Lock()
	defer l.lock.Unlock()
	l.val++
}

func (l *LockCounter) Load() int64 {
	l.lock.Lock()
	defer l.lock.Unlock()
	return l.val
}

| | |____counter.go

package impl

type Counter interface {
	Increment()
	Load() int64
}

| | |____atomiccounter.go

package impl

import "sync/atomic"

type AtomicCounter struct {
	val int64
}

func (a *AtomicCounter) Increment() {
	atomic.AddInt64(&a.val, 1)
}

func (a *AtomicCounter) Load() int64 {
	return atomic.LoadInt64(&a.val)
}

| | |____nonlockcounter.go

package impl

type NonLockCounter struct {
	val int64
}

func (n *NonLockCounter) Increment() {
	n.val++
}

func (n *NonLockCounter) Load() int64 {
	return n.val
}

| |____main.go

package main

import (
	"fmt"
	"github.com/jianan/demo/atomic/impl"
	"sync"
	"time"
)

func test(c impl.Counter) {
	wg := sync.WaitGroup{}
	start := time.Now()

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			c.Increment()
			wg.Done()
		}()
	}

	wg.Wait()
	end := time.Now()
	fmt.Println(c.Load(), end.Sub(start))
}

func main()  {
	c1 := impl.NonLockCounter{}
	c2 := impl.LockCounter{}
	c3 := impl.AtomicCounter{}
	test(&c1)
	test(&c2)
	test(&c3)
}

/*
953 617.268µs
1000 282.257µs
1000 244.219µs
 */

|____synconce
| |____main.go

package main

import (
	"fmt"
	"sync"
)

var (
	instance *singleton

	// 只会执行一次
	// 可用于单例模式的实现
	once sync.Once
)

type singleton struct {
}

func GetInstance() *singleton {
	once.Do(func() {
		fmt.Println("实例化")
		instance = &singleton{}
	})

	once.Do(func() {
		fmt.Println("实例化")
		instance = &singleton{}
	})
	return instance
}

func main() {
	GetInstance()
}

/*
实例化
*/

|____rwmutex
| |____main.go

package main

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

var (
	wg   sync.WaitGroup
	lock sync.RWMutex // 1.350057954s

	// 读写锁,适用于读多写少的情况,性能提升10倍+
	rwlock sync.RWMutex // 110.416132ms
)

func write() {
	rwlock.Lock()
	time.Sleep(10 * time.Millisecond)
	rwlock.Unlock()
	wg.Done()
}

func read() {
	//lock.Lock()
	rwlock.RLock()
	time.Sleep(time.Millisecond)
	rwlock.RUnlock()
	//lock.Unlock()
	wg.Done()
}

func main() {
	start := time.Now()

	for i := 0; i < 10; i++ {
		wg.Add(1)
		go write()
	}

	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go read()
	}

	wg.Wait()
	end := time.Now()
	fmt.Println(end.Sub(start))
}

|____normalmap
| |____main.go

package main

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

var (
	// 并发的map
	safeMap = make(map[string]int)
)

func main() {
	wg := sync.WaitGroup{}

	for i := 0; i < 20; i++ {
		go func(n int) {
			wg.Add(1)
			key := strconv.Itoa(n)
			safeMap[key] = n
			val, ok := safeMap[key]
			if ok {
				fmt.Println("key:", key, "val:", val)
			}
			wg.Done()
		}(i)
	}

	wg.Wait()
}

/*
runtime.throw(0x10d291e, 0x15)
        /usr/local/go/src/runtime/panic.go:774 +0x72 fp=0xc00002e6b8 sp=0xc00002e688 pc=0x1029332
runtime.mapassign_faststr(0x10b2040, 0xc00008a030, 0x10d5530, 0x1, 0x0)
        /usr/local/go/src/runtime/map_faststr.go:211 +0x417 fp=0xc00002e720 sp=0xc00002e6b8 pc=0x1010467
main.main.func1(0xc000088004, 0x3)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:21 +0x94 fp=0xc00002e7d0 sp=0xc00002e720 pc=0x10995e4
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1357 +0x1 fp=0xc00002e7d8 sp=0xc00002e7d0 pc=0x10530e1
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 1 [runnable]:
sync.(*WaitGroup).Wait(0xc000088004)
        /usr/local/go/src/sync/waitgroup.go:103 +0xb3
main.main()
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:30 +0x7f

goroutine 18 [runnable]:
fmt.(*pp).doPrintln(0xc0000a00d0, 0xc000066f80, 0x4, 0x4)
        /usr/local/go/src/fmt/print.go:1168 +0x1e1
fmt.Fprintln(0x10eb2c0, 0xc000080000, 0xc000066f80, 0x4, 0x4, 0x1, 0x0, 0x0)
        /usr/local/go/src/fmt/print.go:264 +0x58
fmt.Println(...)
        /usr/local/go/src/fmt/print.go:274
main.main.func1(0xc000088004, 0x0)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:24 +0x1f1
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 19 [runnable]:
main.main.func1(0xc000088004, 0x1)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 20 [runnable]:
main.main.func1(0xc000088004, 0x2)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 22 [runnable]:
main.main.func1(0xc000088004, 0x4)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:24 +0x142
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 23 [runnable]:
main.main.func1(0xc000088004, 0x5)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 24 [runnable]:
main.main.func1(0xc000088004, 0x6)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 25 [runnable]:
main.main.func1(0xc000088004, 0x7)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 26 [runnable]:
main.main.func1(0xc000088004, 0x8)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 27 [runnable]:
main.main.func1(0xc000088004, 0x9)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 28 [runnable]:
main.main.func1(0xc000088004, 0xa)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 29 [runnable]:
main.main.func1(0xc000088004, 0xb)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 30 [runnable]:
main.main.func1(0xc000088004, 0xc)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 31 [runnable]:
main.main.func1(0xc000088004, 0xd)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 32 [runnable]:
main.main.func1(0xc000088004, 0xe)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 33 [runnable]:
main.main.func1(0xc000088004, 0xf)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 34 [runnable]:
main.main.func1(0xc000088004, 0x10)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 35 [runnable]:
main.main.func1(0xc000088004, 0x11)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 36 [runnable]:
main.main.func1(0xc000088004, 0x12)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

goroutine 37 [runnable]:
main.main.func1(0xc000088004, 0x13)
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18
created by main.main
        /Users/jianan/Documents/my_git/go_module/GoDemo/normalmap/main.go:18 +0x62

Process finished with exit code 2
 */

|____mutex
| |____main.go

package main

import (
	"fmt"
	"sync"
)

var (
	// 共享变量
	global int64

	// 用于指定多少个任务
	wg sync.WaitGroup

	// 互斥锁
	lock sync.Mutex
)

func add() {
	defer wg.Done()
	for i := 0; i < 5000; i++ {
		lock.Lock()
		global++
		lock.Unlock()
	}
}

func main() {
	// 任务数量
	taskNum := 10

	wg.Add(taskNum)
	for i := 0; i < taskNum; i++ {
		go add()
	}

	wg.Wait()

	fmt.Println(global)
}

|____syncmap
| |____main.go

package main

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

var (
	// 并发的map
	safeMap = sync.Map{}
)

func main() {
	wg := sync.WaitGroup{}

	for i := 0; i < 20; i++ {
		go func(n int) {
			wg.Add(1)
			key := strconv.Itoa(n)
			safeMap.Store(key, n)
			val, ok := safeMap.Load(key)
			if ok {
				fmt.Println("key:", key, "val:", val)
			}
			wg.Done()
		}(i)
	}

	wg.Wait()
}

/*
key: 3 val: 3
key: 1 val: 1
key: 0 val: 0
key: 8 val: 8
key: 5 val: 5
key: 6 val: 6
key: 7 val: 7
key: 4 val: 4
key: 10 val: 10
key: 9 val: 9
key: 11 val: 11
key: 12 val: 12
key: 13 val: 13
key: 14 val: 14
key: 15 val: 15
key: 16 val: 16
key: 17 val: 17
key: 18 val: 18
key: 2 val: 2
key: 19 val: 19
*/


 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!