当前位置: 首页 > news >正文

赣州网站建设公司体验式营销经典案例

赣州网站建设公司,体验式营销经典案例,安徽理工大学新校区建设网站,网站建设咋做1. goroutine Go语言通过go关键字来启动一个goroutine。注意:go关键字后面必须跟一个函数,不能是语句或者其他东西,函数的返回值被忽略。 goroutine有如下特性: go的执行是非阻塞的,不会等待。go后面的函数的返回值…

1. goroutine

Go语言通过go关键字来启动一个goroutine。注意:go关键字后面必须跟一个函数,不能是语句或者其他东西,函数的返回值被忽略

goroutine有如下特性

  • go的执行是非阻塞的,不会等待。
  • go后面的函数的返回值会被忽略。
  • 调度器不能保证多个goroutine的执行次序。
  • 没有父子goroutine的概念,所有的goroutine是平等地被调度和执行的。
  • GO程序在执行时会单独为main函数创建一个goroutine,遇到其他go关键字时再去创建其他的goroutine。
  • GO没有暴露goroutine id给用户,所以不能在一个goroutine里面显式地操作另一个goroutine,不过runtime包提供了一些函数访问和设置goroutine的相关信息。

2. chan 通道

goroutine是Go语言里面的并发执行体,chan是goroutine之间通信和同步的重要组件。

2.1 chan类型

//创建一个无缓冲通道,通道存放元素为datatype
make(chan datatype)//创建一个有10个缓冲的通道,通道存放元素的类型为datatype
make(chan datatype, 10)

操作不同状态的chan会引发三种行为:

panic

  • 向已经关闭的通道写数据会导致panic
  • 重复关闭的通道会导致panic

阻塞

  • 向未初始化的通道写数据或读数据会导致当前goroutine的永久阻塞
  • 向缓冲区已满的通道写入数据会导致goroutine阻塞
  • 通道中没有数据,读取该通道会导致goroutine阻塞

非阻塞

  • 读取已经关闭的通道不会引发阻塞,而是立即返回通道元素类型的零值,可以使用comma, ok语法判断通道是否已经关闭。
  • 向有缓冲且没有满的通道读/写不会引发阻塞。

3. select

select是类UNIX系统提供的一个多路复用系统API,Go语言借用多路复用的概念,提供了select关键字,用于多路监听多个通道。当监听的通道没有状态是可读或可写的,select是阻塞的;只要监听的通道中有一个状态是可读或者可写的,则select就不会阻塞,而是进入处理就绪通道的分支流程。如果监听的通道有多个可读或可写的状态,则select随机选取一个处理。

4. Sync - 处理同步请求

当多个 goroutine 同时进行处理的时候,就会遇到比如同时抢占一个资源,某个 goroutine 等待另一个 goroutine 处理完某一个步骤之后才能继续的需求。 在 golang 的官方文档上,作者明确指出,golang 并不希望依靠共享内存的方式进行进程的协同操作。而是希望通过管道 channel 的方式进行。 当然,golang 也提供了共享内存,锁,等机制进行协同操作的包。sync 包就是为了这个目的而出现的。

4.1 锁

sync 包中定义了 Locker 结构来代表锁。

type Locker interface {Lock()Unlock()
}

并且创造了两个结构来实现 Locker 接口:Mutex 和 RWMutex。

4.1.1 Mutex 互斥锁

Mutex 就是互斥锁,互斥锁代表着当数据被加锁了之后,除了加锁的程序,其他程序不能对数据进行读操作和写操作。 这个当然能解决并发程序对资源的操作。但是,效率上是个问题。当加锁后,其他程序要读取操作数据,就只能进行等待了。

4.1.2 RWMutex 读写锁

读写锁分为读锁和写锁,读数据的时候上读锁,写数据的时候上写锁。有写锁的时候,数据不可读不可写。有读锁的时候,数据可读,不可写。读写锁可以看下面的例子:

package mainimport ("sync""time"
)var m *sync.RWMutex
var val = 0func main() {m = new(sync.RWMutex)go read(1)go write(2)go read(3)time.Sleep(5 * time.Second)
}func read(i int) {m.RLock()time.Sleep(1 * time.Second)println("val: ", val)time.Sleep(1 * time.Second)m.RUnlock()
}func write(i int) {m.Lock()val = 10time.Sleep(1 * time.Second)m.Unlock()
}返回:
val:  0
val:  10

但是如果我们把 read 中的 RLock 和 RUnlock 两个函数给注释了,就返回了 :

val:  10
val:  10

这个就是由于读的时候没有加读锁,在准备读取 val 的时候,val 被 write 函数进行修改了。

4.2 Once

有的时候,我们多个 goroutine 都要过一个操作,但是这个操作我只希望被执行一次,这个时候 Once 就上场了。比如下面的例子 :

package mainimport ("fmt""sync""time"
)func main() {var once sync.OnceonceBody := func() {fmt.Println("Only once")}for i := 0; i < 10; i++ {go func() {once.Do(onceBody)}()}time.Sleep(3e9)
}

只会打出一次 "Only once"。

4.3 WaitGroup 和 Cond

一个 goroutine 需要等待一批 goroutine 执行完毕以后才继续执行,那么这种多线程等待的问题就可以使用 WaitGroup 了。

package mainimport ("fmt""sync"
)func main() {wp := new(sync.WaitGroup)wp.Add(10);for i := 0; i < 10; i++ {go func() {fmt.Println("done ", i)wp.Done()}()}wp.Wait()fmt.Println("wait end")
}

还有个 sync.Cond 是用来控制某个条件下,goroutine 进入等待时期,等待信号到来,然后重新启动。比如:

package mainimport ("fmt""sync""time"
)func main() {locker := new(sync.Mutex)cond := sync.NewCond(locker)done := falsecond.L.Lock()go func() {time.Sleep(2e9)done = truecond.Signal()}()if (!done) {cond.Wait()}fmt.Println("now done is ", done);
}

这里当主 goroutine 进入 cond.Wait 的时候,就会进入等待,当从 goroutine 发出信号之后,主 goroutine 才会继续往下面走。

sync.Cond 还有一个 BroadCast 方法,用来通知唤醒所有等待的 gouroutine。

package mainimport ("fmt""sync""time"
)var locker = new(sync.Mutex)
var cond = sync.NewCond(locker)func test(x int) {cond.L.Lock() // 获取锁cond.Wait()   // 等待通知  暂时阻塞fmt.Println(x)time.Sleep(time.Second * 1)cond.L.Unlock() // 释放锁,不释放的话将只会有一次输出
}
func main() {for i := 0; i < 40; i++ {go test(i)}fmt.Println("start all")cond.Broadcast() //  下发广播给所有等待的 goroutinetime.Sleep(time.Second * 60)
}

主 gouroutine 开启后,可以创建多个从 gouroutine,从 gouroutine 获取锁后,进入 cond.Wait 状态,当主 gouroutine 执行完任务后,通过 BroadCast 广播信号。 处于 cond.Wait 状态的所有 gouroutine 收到信号后将全部被唤醒并往下执行。需要注意的是,从 gouroutine 执行完任务后,需要通过 cond.L.Unlock 释放锁, 否则其它被唤醒的 gouroutine 将没法继续执行。 通过查看 cond.Wait 的源码就明白为什么需要需要释放锁了

func (c *Cond) Wait() {c.checker.check()if raceenabled {raceDisable()}atomic.AddUint32(&c.waiters, 1)if raceenabled {raceEnable()}c.L.Unlock()runtime_Syncsemacquire(&c.sema)c.L.Lock()
}

Cond.Wait 会自动释放锁等待信号的到来,当信号到来后,第一个获取到信号的 Wait 将继续往下执行并从新上锁,如果不释放锁, 其它收到信号的 gouroutine 将阻塞无法继续执行。 由于各个 Wait 收到信号的时间是不确定的,因此每次的输出顺序也都是随机的。


参考:go 语言通道( chan )详解( 二 )

http://www.15wanjia.com/news/36186.html

相关文章:

  • 不备案网站seoheuni
  • 网站建设需要服务器么seo实战
  • 织梦后台 data移除后 网站无法打开百度一级代理商
  • 网站搜索优化找哪家十大it教育培训机构排名
  • 中国建设银行网站 党费网络销售怎么聊客户
  • 有没有类似一起做网店的网站今日国际新闻事件
  • 做视频的网站靠什么收入搜索引擎营销的主要方法
  • seo网站关键词优化排名网站推广优化外包公司
  • 网站被百度收录吗seoul是什么意思
  • 什么什么云用来做网站纹身网站设计
  • 江苏seo网站排名优化网站建设百度推广
  • 公司部门分工关键词优化排名网站
  • 营销型网站建设的定义磁力搜索器 磁力猫
  • 柳州网站建设公司泰安seo培训
  • 上海人才网官网站首页必应搜索
  • 如何在网站做电子杂志百度关键词刷排名软件
  • 做网站在厦门排前5名附近电商培训班
  • 网站开发的前端和后端有哪些框架网站域名查询系统
  • 陕西西安网站建设seo论坛
  • 网站用户账号ip查询产品营销推广的方案
  • 湖州建设公司网站广东深圳疫情最新消息
  • 网站建设教程 迅雷下载百度seo工作室
  • 有没有做外贸的网站啊seo内部优化方案
  • 收企业做网站备案seo网站排名的软件
  • 商务网站建设与维护试卷网络培训中心
  • 网站版面做的很好的公司广州seo排名外包
  • web建立虚拟网站互联网广告投放代理公司
  • 知名网站建设在哪里重庆企业免费建站
  • 免费搭建个人网站的3种实用方法小程序平台
  • 填空秒懂网站网址导航