进程和线程

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. Centos 克隆后端口eth1怎么改回eth0

    复制或克隆后成功并做好后续问题的虚拟机 修改网卡地址vi /etc/udev/rules.d/70-persistent-net.rules 配置ifcfg-eth0脚本,注意HWADDR那行,要和上 ...

  2. HTML5之viewport使用

    好久都没更新博客了,最近一年转型移动端,当然网页端也得兼顾,慢慢写一写基本性的文章,多积累. 本期介绍下viewport的一些使用: 先看看viewport在页面中的样子: <meta name ...

  3. CSS3基础知识(一)

    结构选择器 :nth-child(n) 第几个元素 从1开始设置 :nth-child(2n) 偶数元素 从0开始设置 :nth-child(2n+1) 奇数元素 :nth-of-type(n) :f ...

  4. selenium+python自动化97--unittest参数化(paramunittest)

    前言 paramunittest是unittest实现参数化的一个专门的模块,可以传入多组参数,自动生成多个用例 前面讲数据驱动的时候,用ddt可以解决多组数据传入,自动生成多个测试用例.本篇继续介绍 ...

  5. 0_Simple__vectorAdd + 0_Simple__vectorAdd_nvrtc + 0_Simple__vectorAddDrv

    ▶ 使用 CUDA Runtime API,运行时编译,Driver API 三种接口计算向量加法 ▶ 源代码,CUDA Runtime API #include <stdio.h> #i ...

  6. 0_Simple__simpleVoteIntrinsics + 0_Simple__simpleVoteIntrinsics_nvrtc

    介绍了线程束表决函数的实例(其概念介绍见 http://www.cnblogs.com/cuancuancuanhao/p/7841512.html),并在静态和运行时编译两种条件下进行使用. ▶ 源 ...

  7. 解决报错 Page directive: illegal to have multiple occurrences of contentType with different values (old:

    转自:https://blog.csdn.net/dorothy1224/article/details/78064288

  8. bootstrap做的导航

    顶部导航:nav-tabs 左边导航:nav-list 响应式布局:div嵌套 ~ container.row.ol-lg-X 效果: 源码: <!DOCTYPE html> <ht ...

  9. datasnap 如何监控客户端的连接情况

    如果客户端是TCP/IP是短连接的情况就没有必要了. type pClientConns = ^TClientConns; // 客户连接 TClientConns = record clientid ...

  10. J2SE 8的泛型

    泛型的简单使用 1. 泛型一般用E表示集合中元素;k和v表示Map中的key和value;R表示return值;T/U/S表示任意类型 //(1) 简单单个元素的泛型 Box<String> ...