GO-并发编程

一、并发原理

1、Linux进程之间的通信方式
基于数据传送:管道(字节流)、消息队列(结构化对象)
基于共享内存:共享内存区
异步IPC:操作系统的信号机制(signal)
同步IPC:信号量(semaphore)
套接字(socket)
管道(pipe)

go语言支持的IPC:pipe、signal、socket
goroutine之间的通信方式:channel
2、程序、进程、线程、goroutine之间的区别
程序:存储在磁盘中的静态文件
进程:资源分配的最小单位
线程:CPU调度的最小单位
goroutine:比线程更加轻量级
3、并发与并行的区别
并发:一段时间内,多个程序交替执行
并行:一段时间内,多个程序同时执行
4、多进程、多线程
5、GPM模型

概念:

M(machine):表示一个内核线程
P(processor):表示一个处理器
G(goroutine):表示一个goroutine

对应关系:

一个P对应一个M,会在运行时不断变化
一个P对应一个G队列,即一对多

初始化:

通过debug.SetMaxThreads()设置M的数量,默认值为:10000
通过runtime.GOMAXPROCS()设置P的数量,默认值为CPU的核心数
通过debug.SetMaxStack()设置单个G的最大占空间,64位机器默认值为1G
通过runtime.NumGoroutine()获取当前运行时G的数量

G的七种状态:

Gidle:表示当前G刚被新分配,但还未初始化
Grunnable:表示当前G在可运行队列中等待运行
Grunning:表示正在运行
Gsyscall:表示当前G正在执行某个系统调用
Gwaiting:表示当前G正在阻塞中
Gdead:表示当前G正在闲置,准备下一轮初始化重用
Gcopystack:表示当前G的栈正在被移动

二、协程通信

1、channel(通道)
1.通道是并发安全的,同一时刻,仅有一个G能向通道发送数据,同时也仅有一个能G从通道接收数据
2.向未初始化的通道收发数据,会产生panic
3.向已关闭的通道发送数据,会产生panic
4.重复关闭通道,会产生panic
5.关闭通道应由发送方执行
6.for-range遍历通道时会造成阻塞,直到通道关闭
2、select多路复用(监听多个channel)

break只能中断select语句的执行,通过标签的方式跳出外层for循环
select {} 会永久阻塞

func main() {
	intChan := make(chan int, 10)
	for i:=0;i<10;i++{
		intChan <- i
	}
	close(intChan)
	syncChan := make(chan struct{}, 1)

	go func() {
		Loop:
			for{
				select{
				case e,ok:=<-intChan:
					if !ok{
						fmt.Println("End.")
						break Loop
					}
					fmt.Println("Reveived:", e)
				}
			}
			syncChan <- struct{}{}
	}()
	<-syncChan
}

//Reveived: 0
//Reveived: 1
//Reveived: 2
//Reveived: 3
//Reveived: 4
//Reveived: 5
//Reveived: 6
//Reveived: 7
//Reveived: 8
//Reveived: 9
//End.

三、并发控制

1、原子锁
func main() {
	//加减
	var a int64 = 1
	atomic.AddInt64(&a, 2)
	fmt.Println(a)		//3

	//比较并交换(CAS)
	var b int64 = 1
	r := atomic.CompareAndSwapInt64(&b, 1, 5)
	fmt.Println(r)		//true
	fmt.Println(b)		//5

	//载入,读安全
	var c int64 = 1
	tmp := atomic.LoadInt64(&c)
	fmt.Println(tmp)	//1

	//存储,写安全
	var d int64 = 1
	atomic.StoreInt64(&d, 8)
	fmt.Println(d)		//8

	//交换
	var e int64 = 1
	old := atomic.SwapInt64(&e, 88)
	fmt.Println(old, e)		//1 88
}
2、atomic.Value(原子值)

见:https://studygolang.com/articles/23242
在 Go 语言标准库中,sync/atomic包将底层硬件提供的原子操作封装成了 Go 的函数。但这些操作只支持几种基本数据类型,因此为了扩大原子操作的适用范围,Go 语言在 1.4 版本的时候向sync/atomic包中添加了一个新的类型Value。此类型的值相当于一个容器,可以被用来“原子地"存储(Store)和加载(Load)任意类型的值。

3、sync.Mutex(互斥锁)
var mutex sync.Mutex
mutex.Lock()
mutex.Unlock()
4、sync.RWMutex(读写锁)

多个读操作不互斥

var rwm sync.RWMutex
rwm.Lock()		//写锁定
rwm.Unlock()	//写解锁

rwm.RLock()		//读锁定
rwm.RUnlock()	//读解锁
5、sync.Cond(条件变量)

sync.Cond条件变量基于互斥锁,用于协调多个访问共享资源的线程,如生产者消费者模型,Go中可用channel替代

var mutex sync.RWMutex
cond := sync.NewCond(&mutex)
cond.Wait()					//等待通知
cond.Signal()				//单发通知
cond.Broadcast()			//广播通知
6、sync.Once(只执行一次)
func main() {
	var count1 int
	var count2 int
	var once sync.Once
	for i:=0;i<100;i++{
		once.Do(func() {
			count1++
		})
		count2++
	}
	fmt.Println(count1)		//1
	fmt.Println(count2)		//100
}
7、sync.WaitGroup(协程同步工具)
var wg sync.WaitGroup
wg.Add(1)
wg.Done()
wg.Wait()
8、sync.Pool(临时对象池)

Pool 用来保存和复用临时对象,以减少内存分配,降低CG压力。

9、context包

优雅地管理协程的退出

四、其他

1.怎么控制goroutine数量?

https://juejin.cn/post/7017286487502766093

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值