您现在的位置是:首页 > 学习笔记 > 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读写锁



其实,当我们对一个不会变化的数据只做“读”操作的话,是不存在资源竞争的问题的。因为数据是不变的,不管怎么读取,多少goroutine同时读取,都是可以的。所以问题不是出在“读”上,主要是修改,也就是“写”。修改的数据要同步,这样其他goroutine才可以感知到。所以真正的互斥应该是读取和修改、修改和修改之间,读和读是没有互斥操作的必要的。因此,衍生出另外一种锁,叫做读写锁

读写锁可以让多个读操作并发,同时读取,但是对于写操作是完全互斥的。也就是说,当一个goroutine进行写操作的时候,其他goroutine既不能进行读操作,也不能进行写操作。

GO中的读写锁由结构体类型sync.RWMutex表示,此类型的方法集合中包含两对方法。

一组是对写操作的锁定和解锁,简称“写锁定”和“写解锁”:
func (*RWMutex)Lock()
func (*RWMutex)Unlock()

另一组表示对读操作的锁定和解锁,简称为“读锁定”与“读解锁”:
func (*RWMutex)RLock()
func (*RWMutex)RUnlock()

示例如下:

package main

import (
   "sync"
   "math/rand"
   "time"
   "fmt"
)

var count int

var mutex sync.RWMutex

func write(n int) {
   rand.Seed(time.Now().UnixNano())
   fmt.Printf("写 goroutine %d 正在写数据...\n", n)
   mutex.Lock()
   num := rand.Intn(500)
   count = num
   fmt.Printf("写 goroutine %d 写数据结束,写入新值 %d\n", n, num)
   mutex.Unlock()

}
func read(n int) {
   mutex.RLock()
   fmt.Printf("读 goroutine %d 正在读取数据...\n", n)
   num := count
   fmt.Printf("读 goroutine %d 读取数据结束,读到 %d\n", n, num)
   mutex.RUnlock()
}
func main() {
   for i := 0; i < 6; i++ {
      go read(i + 1)
   }
   for i := 0; i < 6; i++ {
      go write(i + 1)
   }
   time.Sleep(time.Second*5)
}

输出结果:

读 goroutine 1 正在读取数据...
读 goroutine 1 读取数据结束,读到 0
读 goroutine 3 正在读取数据...
读 goroutine 3 读取数据结束,读到 0
写 goroutine 2 正在写数据...
读 goroutine 2 正在读取数据...
读 goroutine 2 读取数据结束,读到 0
写 goroutine 4 正在写数据...
写 goroutine 3 正在写数据...
写 goroutine 5 正在写数据...
写 goroutine 1 正在写数据...
写 goroutine 6 正在写数据...
写 goroutine 2 写数据结束,写入新值 69
读 goroutine 4 正在读取数据...
读 goroutine 4 读取数据结束,读到 69
读 goroutine 6 正在读取数据...
读 goroutine 6 读取数据结束,读到 69
读 goroutine 5 正在读取数据...
读 goroutine 5 读取数据结束,读到 69
写 goroutine 4 写数据结束,写入新值 65
写 goroutine 3 写数据结束,写入新值 83
写 goroutine 5 写数据结束,写入新值 7
写 goroutine 1 写数据结束,写入新值 51
写 goroutine 6 写数据结束,写入新值 308

Process finished with exit code 0

我们在read里使用读锁,也就是RLock和RUnlock,写锁的方法名和我们平时使用的一样,是Lock和Unlock。这样,我们就使用了读写锁,可以并发地读,但是同时只能有一个写,并且写的时候不能进行读操作。

我们从结果可以看出,读取操作可以并行,例如2,3,1正在读取,但是同时只能有一个写,例如1正在写,只能等待1写完,这个过程中不允许进行其它的操作。
处于读锁定状态,那么针对它的写锁定操作将永远不会成功,且相应的Goroutine也会被一直阻塞,因为它们是互斥的。

总结:读写锁控制下的多个写操作之间都是互斥的,并且写操作与读操作之间也都是互斥的,但是,多个读操作之间不存在互斥关系。
 

 7/7   首页 上一页 5 6 7

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

很赞哦! ()

上一篇:面向对象

下一篇:Golang之网络编程

相关文章

文章评论

本站推荐