您现在的位置是:首页 > 学习笔记 > Go语言Go语言

Go并发

冰山2019-02-14【Go语言】人已围观

简介1.并发
1.1并发概述
1.2进程并发
1.3线程并发
1.4协程并发
1.5Go并发
2.Goroutine
2.1Goroutine定义
2.2Goroutine的创建
2.3Goroutine特性
3.channel管道
3.1定义channel变量
3.2无缓冲的channel
3.3有缓冲的channel
3.4关闭channel
4.读写锁与互斥锁
4.1死锁
4.2互斥锁
4.3读写锁



什么是锁呢?就是某个协程(线程)在访问某个资源时先锁住,防止其它协程的访问,等访问完毕解锁后其他协程再来加锁进行访问。

 

4.1死锁


死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

死锁:是 “锁”的一种错误使用状态!!!—— 编程过程中,应“提早”避免。

常见的死锁:
 
1)同一个goroutine中,使用同一个 channel 读写。
 
2) 2个 以上的go程中, 使用同一个 channel 通信。 读写channel 先于 go程创建。
 
3) 2个以上的go程中,使用多个 channel 通信。 A go 程 获取channel 1 的同时,尝试使用channel 2, 同一时刻, B go 程 获取channel 2 的同时,尝试使用channel 1
 
4)在go语言中, channel 和 读写锁、互斥锁 尽量避免交叉混用——“隐形死锁”,如果必须使用。推荐借助“条件变量”。
 

4.2互斥锁



每个资源都对应于一个可称为 "互斥锁" 的标记,这个标记用来保证在任意时刻,只能有一个协程(线程)访问该资源,其它的协程只能等待。互斥锁是传统并发编程对共享资源进行访问控制的主要手段,它由标准库sync中的Mutex结构体类型表示。sync.Mutex类型只有两个公开的指针方法,Lock和Unlock。Lock锁定当前的共享资源,Unlock进行解锁。

在使用互斥锁时,一定要注意:对资源操作完成后,一定要解锁,否则会出现流程执行异常,死锁等问题。通常借助defer。锁定后,立即使用defer语句保证互斥锁及时解锁。

示例所示:

var mutex sync.Mutex // 定义互斥锁变量 mutex

func write(){
   mutex.Lock( )
   defer mutex.Unlock( )
}
我们可以使用互斥锁来解决任务编程的问题,如下所示:
package main

import (
   "sync"
   "fmt"
   "time"
)

var mut sync.Mutex

func printer(str string) {
   //mut.Lock()
   //defer mut.Unlock()
   for _, data := range str {
      fmt.Printf("%c", data)
   }
   fmt.Println()
}
func person1() {
   printer("hello")
}
func person2() {
   printer("world")
}
func main() {
   go person1()
   person2()
time.Sleep(time.Second)
}

输出结果:
worhello
ld

让我们加上互斥锁

package main

import (
   "sync"
   "fmt"
   "time"
)

var mut sync.Mutex

func printer(str string) {
   mut.Lock()
   defer mut.Unlock()
   for _, data := range str {
      fmt.Printf("%c", data)
   }
   fmt.Println()
}
func person1() {
   printer("hello")
}
func person2() {
   printer("world")
}
func main() {
   go person1()
   person2()
time.Sleep(time.Second)
}

输出结果:
world
hello

程序执行结果与多任务资源竞争时一致。最终由于添加了互斥锁,可以按序先输出hello再输出 world。但这里需要我们自行创建互斥锁,并在适当的位置对锁进行释放。
 

4.3读写锁


互斥锁的本质是当一个goroutine访问的时候,其他goroutine都不能访问。这样在资源同步,避免竞争的同时也降低了程序的并发性能。程序由原来的并行执行变成了串行执行。

 6/7   首页 上一页 4 5 6 7 下一页 尾页

  • 微信扫一扫~
  • 支付宝扫一扫~

很赞哦! ()

上一篇:面向对象

下一篇:Golang之网络编程

相关文章

文章评论

本站推荐