进程和线程

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之并发篇的更多相关文章

  1. golang的并发

    Golang的并发涉及二个概念: goroutine channel goroutine由关键字go创建. channel由关键字chan定义 channel的理解稍难点, 最简单地, 你把它当成Un ...

  2. golang的并发不等于并行

    先 看下面一道面试题: func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < ...

  3. go---weichart个人对Golang中并发理解

    个人觉得goroutine是Go并行设计的核心,goroutine是协程,但比线程占用更少.golang对并发的处理采用了协程的技术.golang的goroutine就是协程的实现. 十几个gorou ...

  4. golang实现并发爬虫三(用队列调度器实现)

    欲看此文,必先可先看: golang实现并发爬虫一(单任务版本爬虫功能) gollang实现并发爬虫二(简单调度器) 上文中的用简单的调度器实现了并发爬虫. 并且,也提到了这种并发爬虫的实现可以提高爬 ...

  5. Java并发篇

    Java并发篇 作者:星晴(当地小有名气,小到只有自己知道的杰伦粉) 1. Java锁 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 Synchronized 同步锁 1.4.1 核心组件 ...

  6. 多线程JUC并发篇常见面试详解

    @ 目录 1.JUC 简介 2.线程和进程 3.并非与并行 4.线程的状态 5.wait/sleep的区别 6.Lock 锁(重点) 1.Lock锁 2.公平非公平: 3.ReentrantLock ...

  7. Golang学习-第二篇 搭建一个简单的Go Web服务器

    序言 由于本人一直从事Web服务器端的程序开发,所以在学习Golang也想从Web这里开始学起,如果对Golang还不太清楚怎么搭建环境的朋友们可以参考我的上一篇文章 Golang的简单介绍及Wind ...

  8. Golang学习-第一篇 Golang的简单介绍及Windows环境下安装、部署

    序言 这是本人博客园第一篇文章,写的不到位之处,希望各位看客们谅解. 本人一直从事.NET的开发工作,最近在学习Golang,所以想着之前学习的过程中都没怎么好好的将学习过程记录下来.深感惋惜! 现在 ...

  9. 说说Golang goroutine并发那些事儿

    摘要:今天我们一起盘点一下Golang并发那些事儿. Golang.Golang.Golang 真的够浪,今天我们一起盘点一下Golang并发那些事儿,准确来说是goroutine,关于多线程并发,咱 ...

随机推荐

  1. mysql 笔记分享

    mysql LPAD 和RPAD不足位数补齐填充函数总结一下mysql数据库的一些特征MySQL WHERE 语句优化之我见mysql limit 实例详解mysql 如何实现多表联合更新MySQL ...

  2. Linux火焰图-centos

    centos7.5mini安装 yum install -y yum-utils perf debuginfo-install -y perf #debuginfo-install下载了305MB的文 ...

  3. express基础

    express框架 const express = require("express"); 引入express框架 var app= express(); 实例化   相当于构造函 ...

  4. Java集合类性能分析

    [转]对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和Map这三大类的集合,今天Android吧(ard ...

  5. IP分组交付和转发

    1:交付 网络层监视底层物理网络对分组的处理过程叫做交付,分为直接交付和间接交付 1.1:直接交付 直接交付时,分组的终点是一台与交付着连接在同一个网络上的主机,发生在俩种情况下,分组的源点和终点都在 ...

  6. java8函数式编程(转载)

    1. 概述 1.1 函数式编程简介 我们最常用的面向对象编程(Java)属于命令式编程(Imperative Programming)这种编程范式.常见的编程范式还有逻辑式编程(Logic Progr ...

  7. Dark theme for Texstudio - TeX - LaTeX

    Dark theme for Texstudio ~~~  1.window系统如下操作 ~~~ 1. texstudio的配置文件texstudio 的配置文件在~/.config/texstudi ...

  8. MacBook Pro 一月使用体验

    从 2013 年开始,就特别想买 MBP,终于在 2015 年的尾巴用上了 MBPR.原本是要在使用一周后写一份使用体验的,但因为懒,现在拖到一个月了,刚好现在也是2016年的一月,就把标题改成一月使 ...

  9. springboot实现国际化

    1.编写配置文件 2.在application.properties中添加 i18n指的是国际化所在包名 3.实现国际化的接口 4.在配置类中

  10. IdUDPServer中文汉字乱码 及IdTCPClient

    官网 http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdTCPServer_OnExec ...