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 ...
随机推荐
- 分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace【转】
转自:http://bbs.armfly.com/read.php?tid=15377 Bus Hound官方下载地址:http://perisoft.net/bushound/ Bus Hound ...
- Jenkins安装配置过程及问题详解
1:去官网下载jenkins.war包. 官网地址:http://Jenkins-ci.org/ 下载win版 官网镜像地址:http://mirrors.jenkins-ci.org/war-sta ...
- appium的使用
这套教程年久失修,问题的人也比较多,于是,我重新整理了一套appium入门教程. appium新手入门(1)—— appium介绍 appium新手入门(2)—— 安装 Android SDK app ...
- 查看Linux上的CPU核心数、线程数
grep "physical id" /proc/cpuinfo|sort -u grep "cpu cores" /proc/cpuinfo|uniq gre ...
- python模块之os.path
对文件路径的操作 os.path.split(p)函数返回一个路径的目录名和文件名. os.path.splitext():分离文件名与扩展名 os.path.isfile()和os.path.isd ...
- 怎样用css来美化一个html页面
# 转载请留言联系 我们都知道html写出来的东西是一个文本内容,很单调.和我们平时刷网页看到的内容不一样.那普通的网页是怎样对html超文本进行装饰的呢?没错,就是CSS. css的基本语法 选择器 ...
- ORM-班级信息系统
ORM版学员管理系统 班级表 表结构 class Class(models.Model): id = models.AutoField(primary_key=True) # 主键 cname = m ...
- hdu 1348(凸包)
Wall Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Go语言,互斥锁使用
package main import ( "fmt" "runtime" "sync" ) var ( counter int wg sy ...
- django web 自定义通用权限控制
需求:web系统有包含以下5个url,分别对于不同资源: 1.stu/add_stu/ 2.stu/upload_homework/ 3.stu/query_homework/ 4.stu/add_r ...