七叶笔记 » golang编程 » 快速掌握Golang锁机制和并发基础

快速掌握Golang锁机制和并发基础

golang并发知识点总结

1. go申明 goroutine,也可以申明匿名函数,就表示开启多协程并发访问

2. go多个goroutine通信,使用channel,必须用 info:=make(chan string) 格式定义,即用make关键字

3. go申明的并发访问方法,要考虑多个协程同时执行对公共资源的占用和读写,如磁盘读写,网络访问,数据库访问等,下面例子体现并发访问导致的“事务不一致”问题,以及解决方法

4. golang 加锁机制非常轻量简洁 。

go 共享锁定义 mutex := &sync.Mutex{} 传递锁的指针,要注意多个协程要用一个共享锁,传入不同的锁,不能达到加锁的功能。

实例看懂并发和锁

 const (
openLock = true
)

func main2() {
gfile.PutContents("content.txt", "")

concurrency()
chuan()
}
func chuan() {
gproc.StartTime()
// 串行 访问十次 非并发,每次协程id不变
for i := 0; i < 10; i++ {
info := goMethod1("串行", nil)
glog.Debug(info)
}
glog.Info("串行访问十次结束,耗时:", gproc.Uptime())
}
func concurrency() {
//取锁地址
mutex := &sync.Mutex{}

gproc.StartTime()
//并发访问十次
//info:=make(chan string)
for i := 0; i < 10; i++ {
//传递共享锁指针
go goMethod1("并行", mutex)
}
glog.Info("并发访问十次结束,耗时:", gproc.Uptime())

}

//这里的锁是来自上层主线程的共享锁
func goMethod1(mtype string, mutex *sync.Mutex) string {
if mutex != nil && openLock {
mutex.Lock()
defer mutex.Unlock()
}
info := mtype + "访问协程id:" + (strconv.FormatUint(GetGoroutineID(), 10)) + "\r\n"
gutil.TryCatch(func() {
//故意写入两次体验锁机制保证每一个协程事务一致,锁机制
gfile.PutContentsAppend("content.txt", info)
gfile.PutContentsAppend("content.txt", info)

}, func( exception  interface{}) {
glog.Error(exception)
})

return info

}
func GetGoroutineID() uint64 {
b := make([] byte , 64)
 runtime .Stack(b, false)
b =  bytes .TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
  

不加锁文件内容

加锁以后文件内容

结果分析

上面代码执行两种结果如图所示。

不加锁文件内容:方法写入的两句话没法连续写入文件。

加锁以后文件内容:方法写入的两句话连续写入文件。

有锁,就可以保障方法对共享资源的“事务一致性”。

相关文章