一、多线程定义:

所谓的多线程,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 的使用的更多相关文章

  1. 谈谈Golang中goroutine的调度问题

    goroutine的调度问题,同样也是我之前面试的问题,不过这个问题我当时并不是很清楚,回来以后立马查阅资料,现整理出来备忘. 有一些预备知识需要说明,就是操作系统中的线程.操作系统中的线程分为两种: ...

  2. golang中goroutine池的使用

    1. 概念本质上是生产者.消费者模型可以有效的控制goroutine数量,防止暴涨案例:生成一个随机数,计算该随机数每一个数字相加的和,例如:123:1+2+3=6主协程负责生产数据发送到待处理通道中 ...

  3. golang中goroutine

    1. 概念 goroutine 奉行通过通信来共享内存,而不是共享内存来通信 goroutine 是由go的运行时(runtime)调度和管理的 go程序会智能的将goroutine中的任务合理的分配 ...

  4. golang中goroutine协程调度器设计策略

    goroutine与线程 /* goroutine与线程1. 可增长的栈os线程一般都有固定的栈内存,通常为2MB,一个goroutine的在其声明周期开始时只有很小的栈(2KB),goroutine ...

  5. gf框架之grpool - 高性能的goroutine池

    Go语言中的goroutine虽然相对于系统线程来说比较轻量级,但是在高并发量下的goroutine频繁创建和销毁对于性能损耗以及GC来说压力也不小.充分将goroutine复用,减少goroutin ...

  6. 第三章 Goroutine调度策略(16)

    本文是<Go语言调度器源代码情景分析>系列的第16篇,也是第三章<Goroutine调度策略>的第1小节. 在调度器概述一节我们提到过,所谓的goroutine调度,是指程序代 ...

  7. Go语言调度器之盗取goroutine(17)

    本文是<Go语言调度器源代码情景分析>系列的第17篇,也是第三章<Goroutine调度策略>的第2小节. 上一小节我们分析了从全局运行队列与工作线程的本地运行队列获取goro ...

  8. go中的关键字-go(上)

    1. goroutine的使用 在Go语言中,表达式go f(x, y, z)会启动一个新的goroutine运行函数f(x, y, z),创建一个并发任务单元.即go关键字可以用来开启一个gorou ...

  9. golang中锁mutex的实现

    golang中的锁是通过CAS原子操作实现的,Mutex结构如下: type Mutex struct {     state int32                     sema  uint ...

随机推荐

  1. Buildroot自动化交叉编译工具:其一【转】

    转自:http://blog.csdn.net/youyudehexie/article/details/7583657 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] Bui ...

  2. python 复习 4-1 函数、参数、返回值、递归

    函数 完成特定功能的一个语句组,这个语句组可以作为一个单位使用,并且给它组语句取一个名子,即函数名 可以通过函数名在程序不同地方多次执行,即函数调用 预定义函数(可以直接使用) 自定义函数(自编写的) ...

  3. jenkins,已令人发指的简发到如此地步了?

    不用tomcat,一条命令.... java -jar jenkins.war

  4. 对tmemorystream的一些改进_delphi教程

    http://www.cnblogs.com/linyawen/archive/2010/12/11/1903072.html 怎么又是关于Stream的,呵呵,应该说只是最近比较关心程式的效率问题, ...

  5. AC日记——中山市选[2009]小明的游戏 bzoj 2464

    2464 思路: 最短路: 代码: #include <cstdio> #include <cstring> #include <iostream> #includ ...

  6. selenium 定位

    一 . chrome的调试工具 1)在chrome界面,按F12快捷键,弹出chrome的调试工具 2)找出登录按钮的id和username.password的id  二.XPath工具 安装 为了提 ...

  7. 【Linux命令】du -h --max-depth=1 /usr/local/

    查看文件夹中各文件(夹)的大小 例如 du -h --max-depth=1 /usr/local/ 应用:比如mysql 无法启动,提示:ERROR! Manager of pid-file qui ...

  8. POJ 2387 链式前向星下的SPFA

    (POJ)[http://poj.org/problem?id=2387] Til the Cows Come Home Time Limit: 1000MS Memory Limit: 65536K ...

  9. 51nod 1265 四点共面【计算几何+线性代数】

    1265 四点共面 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出三维空间上的四个点(点与点的位置均不相同),判断这4个点是否在同一个平面内(4点共 ...

  10. AHOI2009中国象棋

    首先以行为阶段,根据象棋的规则,在同一行中,至多只能有两个炮,同理:在同一列中,至多只能有两个炮思考一个可以覆盖整个状态空间的dp数组:dp[i]表示到了第i行接下来我们想:某列中的炮能否通过位运算求 ...