Golang之并发篇
进程和线程 A。进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。 B。线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。 C。一个进程可以创建和撤销多个线程;同一进程中的多个线程之间可以并发执行。

并发和并行
并发:多线程程序在一个核的cpu上运行
并行:多线程程序在多个核的cpu上运行
举例。。一个妈给一个碗给多个小孩喂饭,,是并发
一个妈给每个小孩一人一个碗,就是并行

并发 并行
协程和线程
协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级协程,这些用户级线程的调度也是自己实现的。
线程:一个线程上可以跑多个协程,协程是轻量级的线程。
例子
package main import (
"fmt"
"time"
) func test() {
var i int
for {
fmt.Println(i)
time.Sleep(time.Second)
i++
}
}
func main() {
go test() //起一个协程执行test()
for {
fmt.Println("i : runnging in main")
time.Sleep(time.Second )
}
}
-

--

设置Golang运行的cpu核数。
1.8版本以上,默认跑多个核
package main import (
"fmt"
"runtime"
) func main() {
num := runtime.NumCPU()
runtime.GOMAXPROCS(num)
fmt.Println(num)
}
并发计算
package main import (
"fmt"
"sync"
"time"
) var (
m = make(map[int]uint64)
lock sync.Mutex
) type task struct {
n int
} func calc(t *task) {
var sum uint64
sum =
for i := ; i < t.n; i++ {
sum *= uint64(i)
}
fmt.Println(t.n, sum)
lock.Lock()
m[t.n] = sum
lock.Unlock() } func main() {
for i := ; i < ; i++ {
t := &task{n: i}
go calc(t)//并发执行,谁快谁先出
}
time.Sleep( * time.Second)
//lock.Lock()
//for k, v := range m {
// fmt.Printf("%d!=%v\n", k, v)
//}
//lock.Unlock()
}
并发计算
Channel
channel概念
a。类似unix中的管道(pipe)
b.先进先出
c。线程安全,多个goroutine同时访问,不需要枷锁
d。channel是有类型的,一个整数的channel只能存整数
channel声明
var name chan string
var age chan int
var mapchan chan map[string]string
var test chan student
var test1 chan *student
channel初始化
使用make进行初始化
var test chan int
test = make(chan int,) var test chan string
test=make(chan string,)
channel基本操作
从channel读取数据
var testChan chan int
testChan = make(chan int, )
var a int
a = <-testChan
-从channel写入数据
var testChan chan int
testChan = make(chan int, )
var a int =
testChan <- a
第一个例子
package main
import "fmt"
type student struct {
name string
}
func main() {
var stuChan chan *student
stuChan = make(chan *student, )
stu := student{name: "stu001"}
stuChan <- &stu
var stu01 interface{}
stu01 = <-stuChan
var stu02 *student
stu02, ok := stu01.(*student)
if !ok {
fmt.Println("can not convert")
return
}
fmt.Println(stu02)
}
goroutine与channel
package main import (
"fmt"
"time"
) //起一个读的协程
func write(ch chan int) {
for i := ; i < ; i++ {
ch <- i
}
} func read(ch chan int) {
for {
var b int
b = <-ch
fmt.Println(b)
}
} func main() {
intChan := make(chan int, )
go write(intChan)
go read(intChan)
time.Sleep( * time.Second)
}
读,取,字符串
package main import (
"fmt"
"time"
) func sendData(ch chan string) {
ch <- "Washington"
ch <- "Tripoli"
ch <- "London"
ch <- "Beijing"
ch <- "Tokio"
} func getData(ch chan string) {
var input string
for {
input = <-ch
fmt.Println(input)
}
} func main() {
ch := make(chan string)
go sendData(ch)
go getData(ch)
time.Sleep( * time.Second)
}
读取字符串
Channel缓冲区
只能放一个元素的testChan
var testChan chan int
testChan = make(chan int)
var a int
a = <-testChan
-
testChan是带缓冲区的chan,一次可以放10个元素
var testChan chan int
testChan = make(chan int, )
var a int =
testChan <- a
-
package main import (
"fmt"
"sync"
"time"
) var (
m = make(map[int]uint64)
lock sync.Mutex
) type task struct {
n int
} func calc(t *task) {
var sum uint64
sum =
for i := ; i < t.n; i++ {
sum *= uint64(i)
}
fmt.Println(t.n, sum)
lock.Lock()
m[t.n] = sum
lock.Unlock()
} func main() {
for i := ; i < ; i++ {
t := &task{n: i}
go calc(t)
}
time.Sleep( * time.Second)
lock.Lock()
for k, v := range m {
fmt.Printf("%d!=%v\n", k, v) }
lock.Unlock()
}
goroutine_lock
package main import (
"fmt"
) func calc(taskChan chan int, resChan chan int, exitChan chan bool) {
for v := range taskChan {
flag := true
for i := ; i < v; i++ {
if v%i == {
flag = false
break
}
}
if flag {
resChan <- v
}
}
fmt.Println("exit")
exitChan <- true
}
func main() {
intChan := make(chan int, )
resultChan := make(chan int, )
exitChan := make(chan bool, )
go func() {
for i := ; i < ; i++ {
intChan <- i
}
close(intChan)
}()
for i := ; i < ; i++ {
go calc(intChan, resultChan, exitChan)
} //等待所有计算的goroutine全部退出
go func() {
for i := ; i < ; i++ {
<-exitChan
fmt.Println("wait goroute", i, "exited")
}
close(resultChan)
}()
for v := range resultChan {
fmt.Println(v)
} }
goroutine_sync
package main
import "fmt"
func send(ch chan int, exitChan chan struct{}) {
for i := ; i < ; i++ {
ch <- i
}
close(ch)
var a struct{}
exitChan <- a
}
func recv(ch chan int, exitChan chan struct{}) {
for {
v, ok := <-ch
if !ok {
break
}
fmt.Println(v)
}
var a struct{}
exitChan <- a
}
func main() {
var ch chan int
ch = make(chan int, )
exitChan := make(chan struct{}, )
go send(ch, exitChan)
go recv(ch, exitChan)
var total =
for _ = range exitChan {
total++
if total == {
break
}
}
}
goroutine_sync2
检测管道是否关闭
package main
import "fmt"
func main() {
var ch chan int
ch = make(chan int, )
for i := ; i < ; i++ {
ch <- i
}
close(ch)
for {
var b int
b, ok := <-ch
//检测管道是否关闭
if ok == false {
fmt.Println("chan is close")
break
}
fmt.Println(b)
}
}
检测管道是否关闭
如何关闭chan
. 使用内置函数close进行关闭,chan关闭之后,for range遍历chan中
已经存在的元素后结束
. 使用内置函数close进行关闭,chan关闭之后,没有使用for range的写法
需要使用,v, ok := <- ch进行判断chan是否关闭
chan的只读和只写
只读的声明
Var 变量的名字 <-chan int
Var readChan <- chan int 只写的声明
Var 变量的名字 chan<- int
Var writeChan chan<- int
package main import "fmt" //只写chan
func send(ch chan<- int, exitChan chan struct{}) {
for i := ; i < ; i++ {
ch <- i
}
close(ch)
var a struct{}
exitChan <- a
} //只读chan
func recv(ch <-chan int, exitChan chan struct{}) {
for {
v, ok := <-ch
if !ok {
break
}
fmt.Println(v)
}
var a struct{}
exitChan <- a
} func main() {
var ch chan int
ch = make(chan int, ) //初始化chan
exitChan := make(chan struct{}, ) go send(ch, exitChan)
go recv(ch, exitChan) var total =
for _ = range exitChan {
total++
if total == {
break
}
} }
只读只写示例chan
不阻塞
package main import "fmt"
import "time" func main() {
var ch chan int
ch = make(chan int, )
ch2 := make(chan int, )
go func() {
var i int
for {
ch <- i
time.Sleep(time.Second)
ch2 <- i * i
time.Sleep(time.Second)
i++
}
}()
for {
select {
case v := <-ch:
fmt.Println(v)
case v := <-ch2:
fmt.Println(v)
case <-time.After(time.Second):
fmt.Println("get data timeout")
time.Sleep(time.Second)
}
}
}
chan不阻塞
Golang之并发篇的更多相关文章
- golang的并发
Golang的并发涉及二个概念: goroutine channel goroutine由关键字go创建. channel由关键字chan定义 channel的理解稍难点, 最简单地, 你把它当成Un ...
- golang的并发不等于并行
先 看下面一道面试题: func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < ...
- go---weichart个人对Golang中并发理解
个人觉得goroutine是Go并行设计的核心,goroutine是协程,但比线程占用更少.golang对并发的处理采用了协程的技术.golang的goroutine就是协程的实现. 十几个gorou ...
- golang实现并发爬虫三(用队列调度器实现)
欲看此文,必先可先看: golang实现并发爬虫一(单任务版本爬虫功能) gollang实现并发爬虫二(简单调度器) 上文中的用简单的调度器实现了并发爬虫. 并且,也提到了这种并发爬虫的实现可以提高爬 ...
- Java并发篇
Java并发篇 作者:星晴(当地小有名气,小到只有自己知道的杰伦粉) 1. Java锁 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 Synchronized 同步锁 1.4.1 核心组件 ...
- 多线程JUC并发篇常见面试详解
@ 目录 1.JUC 简介 2.线程和进程 3.并非与并行 4.线程的状态 5.wait/sleep的区别 6.Lock 锁(重点) 1.Lock锁 2.公平非公平: 3.ReentrantLock ...
- Golang学习-第二篇 搭建一个简单的Go Web服务器
序言 由于本人一直从事Web服务器端的程序开发,所以在学习Golang也想从Web这里开始学起,如果对Golang还不太清楚怎么搭建环境的朋友们可以参考我的上一篇文章 Golang的简单介绍及Wind ...
- Golang学习-第一篇 Golang的简单介绍及Windows环境下安装、部署
序言 这是本人博客园第一篇文章,写的不到位之处,希望各位看客们谅解. 本人一直从事.NET的开发工作,最近在学习Golang,所以想着之前学习的过程中都没怎么好好的将学习过程记录下来.深感惋惜! 现在 ...
- 说说Golang goroutine并发那些事儿
摘要:今天我们一起盘点一下Golang并发那些事儿. Golang.Golang.Golang 真的够浪,今天我们一起盘点一下Golang并发那些事儿,准确来说是goroutine,关于多线程并发,咱 ...
随机推荐
- Hive基础之Hive表常用操作
本案例使用的数据均来源于Oracle自带的emp和dept表 创建表 语法: CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name ...
- 20180129周一之学习PYTHON笔记【安装、查看工作目录、】
一,安装过程中多选一个ADD的项,免去设置环境变量. 二,PYAUTOGUI模块控制键鼠. IMAGE模块. ----------------------python 如何查看与更换工作目录----- ...
- 浏览器。浏览器对象检测、Chrome调试工具
chrome浏览器的flash问题: 2017-12-26 chrome浏览器的flash有无法显示无法正常运行的问题时,解决方法如下: https://qzonestyle.gtimg.cn/qzo ...
- 3. 修改myeclipse工作区间默认编码和jsp的默认编码
1.windows - preferences - General - Workspace 2.windows - preferences - MyEclipse - Files and Editor ...
- 1. myeclipse设置jsp默认打开方式为jsp Editor
1.windows - preferences - General - Editors - File Associations
- leetcode326
public class Solution { public bool IsPowerOfThree(int n) { && ( % n == ); } } https://leetc ...
- Java架构技术知识点梳理
Java程序员应该加以重视: 吃透基础技术 养成良好的阅读源码的习惯 有长期的技术学习规划 下面,我们来一起逐条看看,特别是第 3 个方法. 想要做到年薪50万,首先你自己必须是高水平的程序员! 能年 ...
- Activity服务类-8 RuntimeService服务类
一共89个接口1.启动流程实例(20个方法)//使用给定的键在流程定义的最新版本中启动一个新的流程实例.ProcessInstance startProcessInstanceByKey(String ...
- WP8.1 页面跳转,overwrite后退键
In 8.1 we use the below code to navigate between pages: this.Frame.Navigate(typeof(PivotPage)); In 8 ...
- Haskell语言学习笔记(36)Data.List.Zipper
ListZipper 模块 $ cabal install ListZipper Installed ListZipper-1.2.0.2 Prelude> :m +Data.List.Zipp ...