其他分享
首页 > 其他分享> > GO-并发安全

GO-并发安全

作者:互联网

资源竞争


原子操作


使用atomic封装原子操作,解除资源竞争,避免脏写

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var n int32

func inc() {
	n++
}

func inc2() {
	atomic.AddInt32(&n, 1)
}

func main() {
	const P = 100
	wg := sync.WaitGroup{}
	wg.Add(P)
	for i := 0; i < P; i++ {
		go func() {
			defer wg.Done()
			inc2()
		}()
	}
	wg.Wait()
	fmt.Printf("n=%d\n", n)
	// fmt.Printf("n=%d\n", atomic.LoadInt32(&n))
}

// go run .\atomic_channel.go
n=100

读写锁


示例

var lock sync.RWMutex

func main() {
	lock.Lock // 写锁
	n++       // 临界区-锁和释放锁之间的代码
	lock.Unlock // 释放写n锁

	lock.RLock //读锁
  fmt.Printf("n=%d\n", n)
	lock.RUnlock //释放读锁
}

容器的并发安全性


并发修改数组

package main

import (
	"fmt"
	"sync"
)

var arr = [10]int{}

func main() {
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 1; i < 10; i += 2 {
			arr[i] = 3
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 10; i += 2 {
			arr[i] = 4
		}
	}()
	wg.Wait()
	fmt.Println(arr)
}

// go run .\collection_safety.go
[4 3 4 3 4 3 4 3 4 3]

并发修改slice

package main

import (
	"fmt"
	"sync"
)

var arr = make([]int, 10)

func main() {
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 1; i < 10; i += 2 {
			arr[i] = 3
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 10; i += 2 {
			arr[i] = 4
		}
	}()
	wg.Wait()
	fmt.Println(arr)
}

// go run .\collection_safety.go
[4 3 4 3 4 3 4 3 4 3]

并发修改struct

package main

import (
	"fmt"
	"sync"
)

type Student struct {
	Name string
	Age  int
}

var student = Student{Name: "tom", Age: 18}

func main() {
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() {
		defer wg.Done()
		student.Name = "test1"
	}()
	go func() {
		defer wg.Done()
		student.Name = "test2"
		student.Age = 22
	}()
	wg.Wait()
	fmt.Println(student)
}

// go run .\collection_safety.go
{test1 22}
// go run .\collection_safety.go
{test2 22}

并发修改map

package main

import (
	"fmt"
	"sync"
)

var dict = make(map[int]string, 10)

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

	wg.Add(2)
	go func() {
		defer wg.Done()
		dict[1] = "Tom"
	}()
	go func() {
		defer wg.Done()
		dict[1] = "jieke"
	}()
	wg.Wait()

	for i, v := range dict {
		fmt.Printf("%d: %s\n", i, v)
	}
}

// 概率性报错
// go run .\collection_safety.go
fatal error: concurrent map writes

goroutine 6949 [running]:
runtime.throw(0x4d2ca3, 0x15)
        E:/Go/src/runtime/panic.go:1116 +0x79 fp=0xc000041f50 sp=0xc000041f20 pc=0x432f99
runtime.mapassign_fast64(0x4b5d40, 0xc00006e330, 0x1, 0xc000050528)
        E:/Go/src/runtime/map_fast64.go:176 +0x311 fp=0xc000041f90 sp=0xc000041f50 pc=0x410461
main.main.func1(0xc0000120a0)
        E:/GO_projectv/collection_safety.go:25 +0x75 fp=0xc000041fd8 sp=0xc000041f90 pc=0x4a0845
runtime.goexit()
        E:/Go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000041fe0 sp=0xc000041fd8 pc=0x45daa1
created by main.main
        E:/GO_project/collection_safety.go:23 +0x8d

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000120a8)
        E:/Go/src/runtime/sema.go:56 +0x49
sync.(*WaitGroup).Wait(0xc0000120a0)
        E:/Go/src/sync/waitgroup.go:130 +0x6b
main.main()
        E:/GO_project/collection_safety.go:31 +0xbd
exit status 2

使用sync.Map

package main

import (
	"fmt"
	"sync"
)

var dict sync.Map

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

	for i := 0; i < 10000000; i++ {
		wg.Add(2)
		go func() {
			defer wg.Done()
			dict.Store(1, "tom")
		}()
		go func() {
			defer wg.Done()
			dict.Store(2, "jieke")
		}()
		wg.Wait()
	}

	dict.Range(func(key, value interface{}) bool {
		fmt.Printf("%d: %s\n", key.(int), value.(string))
		return true
	})
}

标签:wg,func,安全,fmt,sync,并发,go,GO,main
来源: https://www.cnblogs.com/Otiger/p/16221792.html