golang协程同步的几种方法


本文简要介绍下go中协程的几种同步方法。

协程概念简要理解

协程类似线程,是一种更为轻量级的调度单位,但协程还是不同于线程的,线程是系统级实现的,常见的调度方法是时间片轮转法,如每隔10ms切换一个线程执行。

协程则是应用软件级实现,它和线程的原理差不多,当一个协程调度到另一个协程时,将上一个协程的上下文信息压入堆栈,来回切换。一个线程可以跑很多个协程,由这个线程来调度协程的切换,如果是C/C++的话底层就能通过select/poll/epoll来做,例如微信后台的开源libco库。

golang协程底层不是C,纯go实现,golang的协程应该是目前各类有协程概念的语言中实现的最完整和成熟的,调度是基于GPM模型实现的,有兴趣可以去了解下,这里不扯远了,下面看看协程的同步。

为什么要做同步

至于为什么需要同步呢,类似线程要做同步差不多,现在的cpu都是多核,假设一核一个线程同时一起访问同一块内存中的数据吗,那么可能上一ns第一个线程刚把数据从寄存器拷贝到内存,第二个线程马上又把此数据用它修改的值给覆盖了,这样共享数据变会乱套。

举个例子 :

用2个协程序并发各自增一个全局变量100 0000 次

package main 

import(
"fmt"
"time"
) var share_cnt uint64 = 0 func incrShareCnt() {
for i:=0; i < 1000000; i++ {
share_cnt++
} fmt.Println(share_cnt)
} func main() { for i:=0; i < 2; i++ {
go incrShareCnt()
} time.Sleep(1000*time.Second) }

运行4次 , 可以看到我们虽然自增了200 0000次,但没有一个输出200 0000的结果.

协程的几种同步方法

Mutex

互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

package main

import(
"fmt"
"time"
"sync"
) var share_cnt uint64 = 0 var lck sync.Mutex func incrShareCnt() {
for i:=0; i < 1000000; i++ {
lck.Lock()
share_cnt++
lck.Unlock()
} fmt.Println(share_cnt)
} func main() { for i:=0; i < 2; i++ {
go incrShareCnt()
} time.Sleep(1000*time.Second) }

channel

使用golang的channel, 下面一个典型的生产消费模型

package main 

import(
"fmt"
"time"
"strconv"
) func main() { msg_chan := make(chan string)
done := make(chan bool) i := 0 go func() {
for {
i++
time.Sleep(1*time.Second)
msg_chan <- "on message"
<- done
}
}() go func() {
for {
select {
case msg := <- msg_chan :
i++
fmt.Println(msg + " " + strconv.Itoa(i))
time.Sleep(2*time.Second)
done <- true
}
} }() time.Sleep(20*time.Second)
}

WaitGroup

sync包中的WaitGroup可用等待一组协程的结束。

父协程通过Add方法来设定应等待的线程的数量。

每个被等待的协程在结束时调用Done方法。

同时,主协程里调用Wait方法阻塞至所有线程结束。

package main

import(
"sync"
"net/http"
) var wg sync.WaitGroup
var urls = []string{
"http://www.baidu.com/",
"http://www.taobao.com/",
"http://www.tianmao.com/",
}
func main() { for _, url := range urls {
// Increment the WaitGroup counter.
wg.Add(1)
// Launch a goroutine to fetch the URL.
go func(url string) {
// Decrement the counter when the goroutine completes.
defer wg.Done()
// Fetch the URL.
http.Get(url)
}(url)
}
// Wait for all HTTP fetches to complete.
wg.Wait() }

golang协程同步的几种方法的更多相关文章

  1. python学习道路(day11note)(协程,同步与异步的性能区别,url爬网页,select,RabbitMq)

    1.协程 #协程 又称微线程 是一种用户的轻量级线程 程序级别代码控制 就不用加机器 #不同函数 = 不同任务 A函数切到B函数没有进行cpu级别的切换,而是程序级别的切换就是协程 yelied #单 ...

  2. Linux下线程同步的几种方法

    Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码.  1. 初始化锁 int pthrea ...

  3. 归纳一下:C#线程同步的几种方法

    转自原文 归纳一下:C#线程同步的几种方法 我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态:或者你的程序需要访问一些外部资源如数据库 ...

  4. Python与Golang协程异同

    背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定 ...

  5. 面试必问:Golang高阶-Golang协程实现原理

    引言 实现并发编程有进程,线程,IO多路复用的方式.(并发和并行我们这里不区分,如果CPU是多核的,可能在多个核同时进行,我们叫并行,如果是单核,需要排队切换,我们叫并发) 进程和线程的区别 进程是计 ...

  6. Apache shiro集群实现 (八) web集群时session同步的3种方法

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  7. linux实现共享内存同步的四种方法

    https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...

  8. Golang协程实现流量统计系统(3)

    进程.线程.协程 - 进程:太重 - 线程:上下文切换开销太大 - 协程:轻量级的线程,简洁的并发模式 Golang协程:goroutine Hello world package main impo ...

  9. Java中实现线程同步的三种方法

    实现同步的三种方法 多线程共享数据时,会发生线程不安全的情况,多线程共享数据必须同步. 实现同步的三种方法: 使用同步代码块 使用同步方法 使用互斥锁ReetrantLock(更灵活的代码控制) 代码 ...

随机推荐

  1. NFS服务部署

      NFS介绍 NFS基本概述 NFS(Network File System)网络文件系统主要功能是通过局域网络让不同的主机系统之间可以共享文件或目录.NFS系统和Windows网络共享.网络驱动器 ...

  2. adb adb monkey命令及介绍

    1.adb的组成部分 守护进程,客户端,服务器端`      2.Monkey程序是Google公司提供的一个压力和稳定性测试的工具 3.命令 命令 参数 功能 adb version   查看当前a ...

  3. Java 从入门到进阶之路(十一)

    之前的文章我们介绍了一下 Java 中的继承,接下来我们继续看一下 Java 中的继承. 在有些时候,我们通过类继承的方式可以获取父类的方法,但是有些时候父类为我们提供的方法并不完全符合我们的需求,这 ...

  4. Netty实现丢弃服务协议(Netty4.X学习一)

    何为丢弃服务(Discard Protocol),丢弃服务就是一个协议,是最简单的协议,它的作用是接受到什么就丢弃什么,它对调试网路状态有一定的用处.基于TCP的丢弃服务,服务器实现了丢弃丢弃协议,服 ...

  5. 区块链学习笔记:D04 区块链在各行业领域的应用(二)

    这节课主要是政务领域.版权存证领域.能源领域的应用案例介绍 1.房屋租赁联盟链 特点:真实可信.透明补贴.便于追溯.公共监督 节点:房屋运营节点.房管局节点.社保局节点.财政局节点.教育部门节点(多节 ...

  6. 让微信推送Jenkins构建消息

    Jenkins作为开发必备之神器,各家大小公司都在使用.Jenkins自身内置了基于邮件推送构建结果的功能.但是随着移动互联网的发展,邮件这玩意已经越来越少使用了,是否有一种办法能把jenkins构建 ...

  7. mac mysql start ERROR! The server quit without updating PID file

    在mac下安装完mysql,启动时出现error: ERROR! The server quit without updating PID file (/usr/local/var/mysql/nal ...

  8. HDU5470 Typewriter (SAM+单调队列优化DP)

    Typewriter Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tota ...

  9. 强化学习三:Dynamic Programming

    1,Introduction 1.1 What is Dynamic Programming? Dynamic:某个问题是由序列化状态组成,状态step-by-step的改变,从而可以step-by- ...

  10. BX谷 2019年最新所有人都能学会的数据分析课视频教程

    第一章 数据分析师职业概览 1-1 数据分析师的职业概览免费试学 数据分析师的"钱"景如何 什么人适合学数据分析 数据分析师的临界知识 数据分析师的主要职责 第二章 数据分析和数据 ...