golang 线程与通道
首先我们来看线程,在golang里面也叫goroutine
在读这篇文章之前,我们需要了解一下并发与并行。golang的线程是一种并发机制,而不是并行。它们之间的区别大家可以上网搜一下,网上有很多的介绍。
下面我们先来看一个例子吧
import(
"fmt"
)
funcmain(){
go fmt.Println("1")
fmt.Println("2")
}
在golang里面,使用go这个关键字,后面再跟上一个函数就可以创建一个线程。后面的这个函数可以是已经写好的函数,也可以是一个匿名函数
funcmain(){
vari=
go func(a int) {
fmt.Println(a)
fmt.Println("1")
}(i)
fmt.Println("2")
}
上面的代码就创建了一个匿名函数,并且还传入了一个参数i,下面括号里的i是实参,a是形参。
那么上面的代码能按照我们预想的打印1、2、3吗?告诉你们吧,不能,程序只能打印出2。下面我把正确的代码贴出来吧
import(
"fmt"
"time"
)
funcmain(){
var i =
go func(a int) {
fmt.Println(a)
fmt.Println("1")
}(i)
fmt.Println("2")
time.Sleep(1 * time.Second)
}
我只是在最后加了一行让主线程休眠一秒的代码,程序就会依次打印出2、3、1。
那为什么会这样呢?因为程序会优先执行主线程,主线程执行完成后,程序会立即退出,没有多余的时间去执行子线程。如果在程序的最后让主线程休眠1秒钟,那程序就会有足够的时间去执行子线程。
线程先讲到这里,下面我们来看看通道吧。
通道又叫channel,顾名思义,channel的作用就是在多线程之间传递数据的。
创建无缓冲channel
chreadandwrite
:=make(chan int)
chonlyread := make(<-chan int) //创建只读channel
chonlywrite := make(chan<- int) //创建只写channel
下面我们来看一个例子:
ch :=make(chan int)
ch <- 1
go func() {
<-ch
fmt.Println("1")
}()
fmt.Println("2")
这段代码执行时会出现一个错误: :=make(chan int,1)
ch <-
go func() {
v := <-ch
fmt.Println(v)
}()
time.Sleep(1 * time.Second)
fmt.Println("2")
这样的话程序就会依次打印出1、2
2、把ch<-1这一行代码放到子线程代码的后面,代码如下:
ch :=make(chan int)
go func() {
v := <-ch
fmt.Println(v)
}()
ch <-
fmt.Println("2")
这里就不用让主线程休眠了,因为channel在主线程中被赋值后,主线程就会阻塞,直到channel的值在子线程中被取出。
最后我们看一个生产者和消费者的例子:
import (
"fmt"
"time"
)
func produce(p chan<- int) {
for i := 0; i < 10; i++ {
p <- i
fmt.Println("send:", i)
}
}
func consumer(c <-chan int) {
for i := 0; i < 10; i++ {
v := <-c
fmt.Println("receive:", v)
}
}
func main() {
ch := make(chan int)
go produce(ch)
go consumer(ch)
time.Sleep(1 * time.Second)
}
在这段代码中,因为channel是没有缓冲的,所以当生产者给channel赋值后,生产者这个线程会阻塞,直到消费者线程将channel中的数据取出。消费者第一次将数据取出后,进行下一次循环时,消费者的线程也会阻塞,因为生产者还没有将数据存入,这时程序会去执行生产者的线程。程序就这样在消费者和生产者两个线程间不断切换,直到循环结束。
下面我们再看一个带缓冲的例子:
import (
"fmt"
"time"
)
func produce(p chan<- int) {
for i := 0; i < 10; i++ {
p <- i
fmt.Println("send:", i)
}
}
func consumer(c <-chan int) {
for i := 0; i < 10; i++ {
v := <-c
fmt.Println("receive:", v)
}
}
func main() {
ch := make(chan int, 10)
go produce(ch)
go consumer(ch)
time.Sleep(1 * time.Second)
}
在这个程序中,缓冲区可以存储10个int类型的整数,在执行生产者线程的时候,线程就不会阻塞,一次性将10个整数存入channel,在读取的时候,也是一次性读取。
golang 线程与通道的更多相关文章
- golang协程——通道channel阻塞
新的一年开始了,不管今天以前发生了什么,向前看,就够了. 说到channel,就一定要说一说线程了.任何实际项目,无论大小,并发是必然存在的.并发的存在,就涉及到线程通信.在当下的开发语言中,线程通讯 ...
- go语言关于线程与通道channal
在go语言中,封装了多线程的使用方法,使其变得简单易用. 在这里说说自己一点体会,不正确的地方还是请各位大牛指正. 关于go语言的并发机制,这很简单,在你要执行的函数前面加上go即可 比如: pack ...
- golang go语言通道类型的通道示例 通道的通道
几点注意:go的无缓存通道 通道make 创建后,即使里面是空的,也可以取里面内容.但是程序会被阻塞. 通道的规则是没人取,是不能往里面放的.放的线程会阻塞. 最外层的requestChan相当于一个 ...
- Golang 入门 : channel(通道)
笔者在<Golang 入门 : 竞争条件>一文中介绍了 Golang 并发编程中需要面对的竞争条件.本文我们就介绍如何使用 Golang 提供的 channel(通道) 消除竞争条件. C ...
- golang线程安全
目录 1.golang的map是线程安全的吗?怎么安全使用map 2.线程独享什么,共享什么 3.进程状态转换 4.Log包线程安全吗? 5.写的循环队列是不是线程安全? 6.go协程线程安全吗 7. ...
- [Go] golang无缓冲通道实现工作池控制并发
展示如何使用无缓冲的通道创建一个goroutine池,控制并发频率1.无缓冲通道保证了两个goroutine之间的数据交换2.当所有的goroutine都忙的时候,能够及时通过通道告知调用者3.无缓冲 ...
- 你不得不知的Golang线程模型 [转载]
原著:翟陆续(加多) 资深Java , 著Java并发编程之美 一.前言 本节我们来探讨Go的线程模型,首先我们先来回顾下常见的三种线程模型,然后在介绍Go中独特的线程模型. 二.三种线程模型 线程的 ...
- Golang 线程池
经常会用到协程,但是不能一下开那么多协调,只需要 poolSize 个即可,多了不行.这些个协程在执行完后必须等其完成之后才能进行下一步动作.假定工作方法为 work . package main i ...
- JAVA NIO Socket通道
DatagramChannel和SocketChannel都实现定义读写功能,ServerSocketChannel不实现,只负责监听传入的连接,并建立新的SocketChannel,本身不传输数 ...
随机推荐
- Linux-centos-7.2-64bit 安装配置mysql
2018-04-12 安装在/usr/local/下,配置文件在/etc/my.ini 1.下载mysql安装包到 /usr/local/software cd /usr/local/software ...
- Linux:crontab组件部署linux定时任务
crontab简介 crond 是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务 工具,并且会自动启动c ...
- STL源码剖析 — 空间配置器(allocator)
前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...
- Now trying to drop the old temporary tablespace, the session hangs.
1.描述 问题描述:删除临时表空间时,会话Hangs挂起 SQL> drop tablespace TEMP_B including contents and datafiles; 2.故障诊断 ...
- 页面js脚本与img等资源的下载顺序问题。
引言问题 <img src="background.jpg"><script src="test.js"></script> ...
- [LeetCode] 2 Keys Keyboard 两键的键盘
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- ABP领域层知识回顾之---实体
标题:重温ABP领域层 1. 前言 最近一段时间一直在看<ABP的开发指南>(基于DDD的经典分层架构思想).因为之前一段时间刚看完<领域驱动设计:软件核心复杂性应对之道>, ...
- [测试题]数组(array)
Description Input Output Sample Input1 3 2 75 4 2 Sample Output1 999999732 Sample Explanation1 Sampl ...
- ●51NOD 1705 七星剑
题链: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1705题解: 期望dp,期望的线性性质 (首先对于第k颗星,一定只 ...
- bzoj 2555: SubString
Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...