首页 > 其他分享 >第八章(并发)[上]

第八章(并发)[上]

时间:2023-01-29 22:55:50浏览次数:37  
标签:goroutine 第八章 并发 done func println main

并发和并行的区别

  • 并发:逻辑上具备同时处理多个任务的能力(片面理解:多个进程来回切换执行,用户感知到多个程序同时执行一样)
  • 并行:物理上在同一时刻执行多个并发任务(片面理解:多核cpu分别同时执行多个线程,真正的同时执行)

并行是并发设计的理想执行模式

  • 多线程或多进程是并行的基本条件,但单线程也可用协程协程做到并发。

  • 协程在单个线程上通过主动切换来实现多任务并发

  • goroutine更像是多线程和协程的综合体:运行时创建多个线程来执行并发任务,且任务单元可被调度到其它线程并行执行。能最大线限度提升执行效率,发挥多核处理能力

  • go关键字并非执行并发操作,而是创建一个并发任务单元。新建任务被放置在系统队列中,等待调度器安排合适的系统线程去获取执行权

  • 每个任务单元除保存函数指针,调用参数外,还会分配执行所需的栈内存空间。相比系统默认MB级别的线程栈,goroutine自定义栈初始仅须2KB,所以才能创建成千上万的并发任务。

  • 自定义栈采取按需分配策略,在需要时进行扩容,最大能到GB规模(在不同版本中,自定义栈大小略有不同)

defer一样,goroutine也会立即计算并复制参数。代码如下:

package main

import "time"

var c int

func counter() int {
	c++
	return c
}
func main() {
	a := 100

	go func(x, y int) {
		time.Sleep(time.Second)
		println("goroutine:", x, y)
	}(a, counter()) //立即计算并复制参数 100,1

	a += 100
	println("main:", a, counter()) //200,2

	time.Sleep(time.Second * 3)
}

Wait

  • 进程退出时不会等待并发任务结束,可用channel阻塞,然后发出退出信号
func main() {
	exit := make(chan struct{}) //使用空结构体作为通道元素,用于事件通知
	go func() {
		time.Sleep(time.Second)
		println("goroutine done")
		close(exit) //关闭通道
	}()
	println("main ...")
	<-exit //读取通道,没有数据或通道未关闭时一直阻塞
	println("main exit")
}

  • 如若等待多个任务结束,可使用sync.WaitGroup通过设定计数器,让每个goroutine在退出前递增,直至归零时解除阻塞。
func main() {
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1) //尽管WaitGroup.Add实现了原子操作,但建议在goroutine外累加计数器,以免Add尚未执行,Wait已经退出
		go func(id int) {
			defer wg.Done()
			time.Sleep(time.Second)
			println("goroutine", id, "done.")
		}(i)
	}
	println("main...")
	wg.Wait()
	println("main exit.")
	/*
		main...
		goroutine 5 done.
		goroutine 7 done.
		goroutine 0 done.
		goroutine 9 done.
		goroutine 4 done.
		goroutine 2 done.
		goroutine 3 done.
		goroutine 6 done.
		goroutine 1 done.
		goroutine 8 done.
		main exit.
	*/
}

  • 也可多处使用Wait阻塞,它们都能接收到通知(在1.17.3测试:多处goroutine中使用wait并不会阻塞,也不会接收到通知,)

Goexit

  • Goexit立即终止当前任务,运行时确保所有注册延迟调用被执行。该函数不会影响其它并发任务
func main() {
	exit := make(chan struct{})

	go func() {
		defer close(exit)
		defer println("a")

		func() {
			defer func() {
				println("b", recover() == nil)
			}()

			func() {
				println("c")
				runtime.Goexit()   //立即终止当前goroutine,不会终止已注册的延迟调用函数
				println("c done.") //不会执行
			}()
			println("b done.") //不会执行
		}()
		println("a done.") //不会执行
	}()
	<-exit
	println("main exit.")
}
  • 在main.main里调用Goexit,会等其它goroutine结束后让进程直接崩溃
func main() {
	for i := 0; i < 5; i++ {
		go func(x int) {
			println("goroutine:", x)
		}(i)
	}
	runtime.Goexit() //等待其它goroutine结束后再终止进程
	println("main exit")
	/*goroutine: 0
	  goroutine: 1
	  goroutine: 3
	  goroutine: 2
	  goroutine: 4
	fatal error: no goroutines (main called runtime.Goexit) - deadlock!*/
}

os.Exit会立即终止进程,不会执行延迟调用

标签:goroutine,第八章,并发,done,func,println,main
From: https://www.cnblogs.com/badake/p/17071426.html

相关文章

  • 并发和并行区别
    并发(concurrency):把任务在不同的时间点交给处理器进行处理。在同一时间点,任务并不会同时运行。并行(parallelism):把每一个任务分配给每一个处理器独立完成。在同一时间点,......
  • 实现单线程多并发的几种方式
    单线程爬虫适用于小规模爬虫项目,如果应对大型项目就得实现多线程多并发,那么单线程如何实现多并发,下面几个示例可以一起看看。1、asyncio2、gevent3、Twisted4、Tornado......
  • golang并发编程-生产者消费者模式
    https://blog.csdn.net/qq_55752792/article/details/125917846packagemainimport("fmt""math/rand""sync""time")//JobstructtypeJobst......
  • 【高并发】AQS中的CountDownLatch、Semaphore与CyclicBarrier用法总结
    CountDownLatch概述同步辅助类,通过它可以阻塞当前线程。也就是说,能够实现一个线程或者多个线程一直等待,直到其他线程执行的操作完成。使用一个给定的计数器进行初始化,该......
  • 【Java】用增强for循环遍历元素提示并发修改异常
    做二叉树遍历时使用了增强for循环,但是出现异常:Exceptioninthread"main"java.util.ConcurrentModificationException原因是:迭代器遍历元素的时候,通过集合是不能修改元素......
  • CSAPP随笔: 并发及并行
     并发:通用概念,同时具有多个活动的系统,通过进程的快速切换模拟出来的。 并行:用并发使系统运行得更快。多核处理器:将多个CPU集成到一个电路芯片上。    超......
  • php高并发的瓶颈到底在哪
    说php不适合高并发?问过facebook没?虽然facebook用的是编译型的php,叫hphp,可以跑在类似jvm的虚拟机上,叫hhvm。只不过后来php出了7.x版本甚至8.x之后性能大幅提升,性能和faceboo......
  • 高并发性能指标:QPS、TPS、RT、并发数、吞吐量
    高并发系统系统指标高并发系统核心指标一、QPS,每秒查询QPS:QueriesPerSecond是衡量信息检索系统(例如搜索引擎或数据库)在一秒钟内接收到的搜索流量的一种常见度量......
  • 第八章 数据可视化
    本章主要介绍数据可视化的一些辅助操作,而非制作图表主要内容:利用条形图显示数值情况、依据条件设置(填充)单元格、利用迷你图显示数据及其变化情况1、利用条形图显示数值......
  • 【并发编程】同步容器与并发容器
    文章目录​​1.同步容器类​​​​2.并发容器类​​1.同步容器类(1)为什么会出现同步容器Java集合框架中,主要有四大类别:List、Set、Queue、Map。List、Set、Queue接口分别继承......