go 中goroutine 的使用
一、多线程定义:
所谓的多线程,multithreading。有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。 [1] 在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程(台湾译作“执行绪”),进而提升整体处理性能。
最简单的比喻多线程就像火车的每一节车厢,而进程则是火车
有些程序是一条直线,起点到终点——如简单的hello world,运行打印完,它的生命周期便结束了,像是昙花一现。
有些程序是一个圆,不断循环直到将它切断——如操作系统,一直运行直到你关机。
一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流。
来个简单的例子:
package main import (
"fmt"
// "reflect"
"sync"
"time"
) func thread1(a int) int {
fmt.Println("thread 1 %d", a) sum := 0
for a > 0 {
sum += a
a--
if a == 3 {
time.Sleep(2 * time.Millisecond)
}
} return sum
} func thread2() {
time.Sleep(1 * time.Microsecond)
fmt.Println("thread 2")
} var x int = 0 func main() {
s := []int{10, 9, 8}
var wg sync.WaitGroup
wg.Add(1) time.Sleep(1 * time.Millisecond) go func() {
x = thread1(s[0])
wg.Done()
}()
fmt.Println(x)
wg.Wait()
fmt.Println(x)
// f := false
// str := "adfa"
// flo := 1.1
go thread2() fmt.Println("main thread")
// time.Sleep(10 * time.Millisecond)
fmt.Println(x) }
----------------------------------------------------------------------------------
Catching return values from goroutines
I am a newbie to golang, so please excuse if this is a very basic question. The below code gives compilation error saying 'unexpected go':
x := go doSomething(arg)
func doSomething(arg int) int{
...
return my_int_value
}
I know, I can fetch the return value if call the function normally, without using goroutine. Or I can use channels etc.
My question is why is it not possible to fetch a return value like this from a goroutine.
The strict answer is that you can do that. It's just probably not a good idea. Here's code that would do that:
var x int
go func() {
x = doSomething()
}()
This will spawn off a new goroutine which will calculate doSomething() and then assign the result to x. The problem is: how are you going to use x from the original goroutine? You probably want to make sure the spawned goroutine is done with it so that you don't have a race condition. But if you want to do that, you'll need a way to communicate with the goroutine, and if you've got a way to do that, why not just use it to send the value back?
You can add a WaitGroup to make sure you've finished and wait for it. But as you said, it's just not the way to do it, a channel is. – Not_a_Golfer Jan 6 '14 at 10:44
Why is it not possible to fetch a return value from a goroutine assigning it to a variable?
Run goroutine (asynchronously) and fetch return value from function are essentially controversial actions. When you say go you mean "do it asynchronously" or even simpler: "Go on! Don't wait for the function execution be finished". But when you assign function return value to a variable you are expecting to have this value within the variable. So when you do that x := go doSomething(arg)you are saying: "Go on, don't wait for the function! Wait-wait-wait! I need a returned value be accessible in x var right in the next line below!"
Channels
The most natural way to fetch a value from a goroutine is channels. Channels are the pipes that connect concurrent goroutines. You can send values into channels from one goroutine and receive those values into another goroutine or in a synchronous function. You could easily obtain a value from a goroutine not breaking concurrency using select:
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
// Await both of these values
// simultaneously, printing each one as it arrives.
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
The example is taken from Go By Example
CSP & message-passing
Go is largerly based on CSP theory. The naive description from above could be precisely outlined in terms of CSP (although I believe it is out of scope of the question). I strongly recommend to familiarize yourself with CSP theory at least because it is RAD. These short quotations give a direction of thinking:
As its name suggests, CSP allows the description of systems in terms of component processes that operate independently, and interact with each other solely through message-passing communication.
In computer science, message passing sends a message to a process and relies on the process and the supporting infrastructure to select and invoke the actual code to run. Message passing differs from conventional programming where a process, subroutine, or function is directly invoked by name.
go 中goroutine 的使用的更多相关文章
- 谈谈Golang中goroutine的调度问题
goroutine的调度问题,同样也是我之前面试的问题,不过这个问题我当时并不是很清楚,回来以后立马查阅资料,现整理出来备忘. 有一些预备知识需要说明,就是操作系统中的线程.操作系统中的线程分为两种: ...
- golang中goroutine池的使用
1. 概念本质上是生产者.消费者模型可以有效的控制goroutine数量,防止暴涨案例:生成一个随机数,计算该随机数每一个数字相加的和,例如:123:1+2+3=6主协程负责生产数据发送到待处理通道中 ...
- golang中goroutine
1. 概念 goroutine 奉行通过通信来共享内存,而不是共享内存来通信 goroutine 是由go的运行时(runtime)调度和管理的 go程序会智能的将goroutine中的任务合理的分配 ...
- golang中goroutine协程调度器设计策略
goroutine与线程 /* goroutine与线程1. 可增长的栈os线程一般都有固定的栈内存,通常为2MB,一个goroutine的在其声明周期开始时只有很小的栈(2KB),goroutine ...
- gf框架之grpool - 高性能的goroutine池
Go语言中的goroutine虽然相对于系统线程来说比较轻量级,但是在高并发量下的goroutine频繁创建和销毁对于性能损耗以及GC来说压力也不小.充分将goroutine复用,减少goroutin ...
- 第三章 Goroutine调度策略(16)
本文是<Go语言调度器源代码情景分析>系列的第16篇,也是第三章<Goroutine调度策略>的第1小节. 在调度器概述一节我们提到过,所谓的goroutine调度,是指程序代 ...
- Go语言调度器之盗取goroutine(17)
本文是<Go语言调度器源代码情景分析>系列的第17篇,也是第三章<Goroutine调度策略>的第2小节. 上一小节我们分析了从全局运行队列与工作线程的本地运行队列获取goro ...
- go中的关键字-go(上)
1. goroutine的使用 在Go语言中,表达式go f(x, y, z)会启动一个新的goroutine运行函数f(x, y, z),创建一个并发任务单元.即go关键字可以用来开启一个gorou ...
- golang中锁mutex的实现
golang中的锁是通过CAS原子操作实现的,Mutex结构如下: type Mutex struct { state int32 sema uint ...
随机推荐
- python 多进程锁Lock和共享内存
多进程锁 lock = multiprocessing.Lock() 创建一个锁 lock.acquire() 获取锁 lock.release() 释放锁 with lock: 自动获取.释放锁 类 ...
- 《Java编程思想》笔记 第十六章 数组
1 数组 数组和容器比较,数组的优点也只剩访问效率高这一点了. 2 数组是第一级对象 数组也是一个对象,和其他普通对象一样在堆中创建, int[ ] arr arr是数组的引用. 可以隐式创建数组对 ...
- 任务侦听器(Task listener)
任务侦听器:用于在任务相关的事件发生时执行一段java逻辑或者是表达式 <userTask id="myTask" name="My Task" > ...
- rest_frameword学前准备
CBV CBV(class base views) 就是在视图里使用类处理请求. Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承.封装.多态).所以Dja ...
- Android xmlpull 方式解析xml文件
1.新建一个xml文件,放在res/xml目录下 <?xml version="1.0" encoding="utf-8"?> <citys& ...
- zoj3256
好题,由m的范围知道这肯定是矩阵乘法加速插头dp,关键是怎么写 以往插头dp常用逐格递推,而这道题要求整行逐列递推 这样我们才能构造转移矩阵. 我们可以通过假象一个第0列来将路径转化为回路问题 逐列递 ...
- ajaxfileupload异步上传文件
ajaxfileupload插件可以以异步方式上传文件(其实现:iframe),不像传统那样需要刷新,下面就介绍下其使用 1.HTML部分(先引入jquery): <!DOCTYPE html& ...
- 在Ubuntu 16.04安装 Let’s Encrypt并配置ssl
1.安装前准备 1)要确保python的默认版本为2.7及以上版本. 2)需要配置的apache.nginx需要提前配置绑定域名. 2.安装ssl 在这个https://certbot.eff.org ...
- 图解Javascript——执行上下文
什么是执行上下文? 执行上下文(Execution Context)是ECMAScript规范中用来描述 JavaScript 代码执行的抽象概念,规定了当前代码执行的环境(当前执行代码片段中的变量. ...
- Mathematica作图
第2讲 在Mathematica中作图 一个较强的符号计算系统均有很好的绘图功能,Mathematica也不例外,Mathematica 拥有非常强大的绘图功能.并且提供了一大批基本数学函数的图 ...