当前位置: 首页 > 编程日记 > 正文

Go语言的Channel文章,整个人都感觉不好了

链客,专为开发者而生,有问必答!

此文章来自区块链技术社区,未经允许拒绝转载。

在这里插入图片描述

Go的Channel是一个很强大的并发数据模型,在一个发送者和多个消费者情况下工作得最好,但是如果是多个发送者,那么在Channel关闭时需要协调多个发送者,等待它们发送消费完毕,同时也会导致一个Channel多次关闭的情况,这个问题Go社区已经注意到,并正在试图解决:issue#14601

让我们看看来自

go channels are bad and you should feel bad | jtol一文是如何抱怨Channel有多不好,以下是原文大意转述:

首先,不用质疑的是,该文博主自从2010中期就开始使用Go语言,参与编写了425K行的纯Go代码,并为Go社区提供了不少开源项目。

Go语言是以Channel和Goroutine(轻量线程)著称,它的理论模型主要是基于CSP模型(Communicating Sequential Processes),但是该文博主认为,从程序员角度看,Go的Channel模型实现方式是错误的,它是一个彻底的反模式。

CSP模型是一种高并发计算模型,这种模型本身是试图通过一个通道同步管理发送和接受,但是,如果一旦你引入其他同步机制如互斥锁mutex、semaphore或条件判断变量,你就再也不是纯的CSP了。

下面让我们看看使用GO编写CSP模型,这个案例是关于如何接受到选手的最高分。

首先,使用Game作为数据结构:

type Game struct {
bestScore int
scores chan int
}

这里状态变量bestScore 并不使用互斥锁进行保护,因为我们只有一个goroutine管理这个状态,新的分数是通过一个channel接受的。

func (g *Game) run() {
for score := range g.scores {
if g.bestScore < score {
g.bestScore = score
}
}
}

现在开始一个启动game的构造器:

func NewGame() (g *Game) {
g = &Game{
bestScore: 0,
scores: make(chan int),
}
go g.run()
return g
}

下一步,让我们假设有人给我们一个Player接口,这个接口可以获得分数score,也可能返回错误,因为也许网络连接错误或player已经退出。

type Player interface {
NextScore() (score int, err error)
}

下面是处理player,首先检查错误,然后将接受到的分数发给channel。

func (g *Game) HandlePlayer(p Player) error {
for {
score, err := p.NextScore()
if err != nil {
return err
}
g.scores <- score
}
}

好了,我们有一个Game类型,能够以线程安全方式跟踪Player的最高分。

当你将这个游戏上线运行后,你获得了非常地成功,你的游戏服务器上运行了很多这样的Game程序。但是你会发现人们有时会离开你的游戏,许多游戏里面没有任何玩家,但是游戏本身没有停止而是不停地在循环运行,你被(*Game).run协程搞得不知所措了。

其实这个案例完全可以不使用Channel简单地完成:

type Game struct {
mtx sync.Mutex
bestScore int
}

func NewGame() *Game {
return &Game{}
}

func (g *Game) HandlePlayer(p Player) error {
for {
score, err := p.NextScore()
if err != nil {
return err
}
g.mtx.Lock()
if g.bestScore < score {
g.bestScore = score
}
g.mtx.Unlock()
}
}

这里只是引入了互斥锁,替代了原来的Channel方式。使用传统的同步锁替代CSP的Go channel居然解决了问题。

那么,让我们看看Go语言的Channel背后是什么?Channel是使用锁保证连续访问的线程安全性,使用Channel同步化内存的访问,其实你是在使用锁(banq注:这违背了CSP模型本身定义,CSP存在的前提就是避免使用锁。),锁被线程安全的队列给包装了,那么Go的这个神秘的锁与直接使用标准库中mutex有什么区别?下面是两者性能测试结果:

BenchmarkSimpleSet-8 3000000 391 ns/op
BenchmarkSimpleChannelSet-8 1000000 1699 ns/op

对于unbuffered channel也是同样测试结果。(测试结果表明:Channel性能比mutex性能要差得多)

也许Go的调度器会提高,但是这意味着老的旧的互斥锁和条件变量表现得非常好,更有效,更快速。如果你需要性能,那么就使用这些真正的方法(互斥锁等方法)。

此后,该文作者还指出Channel其实并不能和其他并发原始模型很好地组合在一起。比如Channel和互斥锁放在一起就带来不确定性。

他还指出,在API中使用Channel反而使得问题变得糟糕,你完全可以在没有任何协程情况下使用互斥锁mutexe, semaphores,和回调callbacks编写API,有时,回调函数反而更加强大,虽然,goroutine协程口口声声说是用来替代万恶的回调函数的。协程只是比线程较为轻量,但是较为轻量不代表它是最轻量的。

他还谈到:对一个已经关闭的Channel再进行关闭或发送操作是非常痛苦,如果你要关闭一个Channel,需要将关闭状态进行同步化操作,使用mutex互斥锁等,但是它们又不能很好地协调在一起,为什需要有关闭的状态?因为这样才会防止其他写入者同时写入或关闭一个已经关闭的channel。

相关文章:

图书管理系统(源码)

本文demo下载地址&#xff1a;http://www.wisdomdd.cn/Wisdom/resource/articleDetail.htm?resourceId1070 实例使用java语言实现了一个网页版的图片管理系统, 系统前端使用bootstrap技术&#xff0c;可以进行浏览器适配, 实现功能: 管理图书管书, 管理图书借还信息&#xff0…

linux 如何禁用账号和解除禁用账号

把账号禁用可以有几个方法&#xff1a;1. # usermod -L <username> # usermod -U <username> // 解除禁用2. 修改/etc/passwd文件&#xff0c;可以有几个地方1&#xff09;把第二个字段中的"x"变成其它的字符&#xff0c;该账号就不能…

maya批量命名插件_教你玩转MAYA的四十二精华造诣(第一期)

最近在整理文档时发现我收藏了一篇关于MAYA应用技巧的文章&#xff0c;突然有兴趣看了看&#xff0c;结果发现老版本MAYA中的某些内容很多已经无法应用于新版本。我又上网查了一下&#xff0c;结果发现网上好多帖子和我收藏的这篇内容基本一致&#xff0c;看来好多都是转载和抄…

Go语言开发常见陷阱,你遇到过几个?

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 Go作为一种简便灵巧的语言&#xff0c;深受开发者的喜爱。但对于初学者来说&#xff0c;要想轻松驾驭它&#xff0c;还得做好细节学习工作。 初学者…

sxoi爆炸祭

好吧&#xff0c;纯粹是去玩玩的&#xff0c;我这么一个弱省的蒟蒻&#xff0c;进队纯粹是开玩笑。。。。 Day0 去五中试机&#xff0c;感觉电脑手感不错&#xff0c;打了半个线段树的板子才发现试机要在自己的电脑上试&#xff0c;然后我无奈的搬东西&#xff08;从26号搬到2号…

wiki多个文件一起导入_mac文件信息管理工具EagleFiler for Mac分享给大家

EagleFiler for mac使得管理您的信息方便。它可以让你存档和搜索邮件&#xff0c;网页&#xff0c;PDF文件&#xff0c;字处理文档&#xff0c;图像&#xff0c;等等。使用它可以从不同的来源收集信息。浏览不同类型的文件采用标准的三窗格界面。组织他们到文件夹中&#xff0c…

【bzoj1951】 Sdoi2010—古代猪文

http://www.lydsy.com/JudgeOnline/problem.php?id1951 (题目链接) 题意 废话一堆。。求解&#xff1a;$$g^{\sum_{d|n} C_n^d}~mod~p$$ Solution 真的是数论经典题&#xff0c;什么都用上了。 因为费马小定理&#xff0c;每$p-1$个$g$相乘会得到$1$&#xff0c;那么容易得到&…

区块链之智能合约详解

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 什么是智能合约&#xff1f; 智能合约又称智能合同&#xff0c;是由事件驱动的、具有状态的、获得多方承认的、运行在区块链之上的、且能够根据预设…

子类化内置类型

Python 2.2之后内置类型开始可以子类化了 但是&#xff0c;CPython中的内置类型不会调用用户重写的类的特殊方法。 PyPy的文档中描述了这个问题。subclasses-of-built-in-types 正式情况下&#xff0c;CPython 并没有官方规定内置类型的子类中重写的方法是否会被隐式调用。基本…

网上商城系统源代码_多用户系统商城授权有几种方式?

网上商城系统一般都需要获取正规授权才可以投入商业使用范围&#xff0c;许多系统开发商为了适应不同企业的需求提供了几种不同的授权方式&#xff0c;企业可以选择合适的方式获得系统的使用权。下面HiShop小编就来为大家介绍一下多用户商城系统的授权方式。一、多用户系统商城…

java学习:对synchronized的测试

平时对synchronized这个关键字没有太在意&#xff0c;对它的认识停留在粗略翻了一下百度百科的状态&#xff0c;百度百科对它的解释是&#xff1a; “Java语言的关键字&#xff0c;可用来给对象和方法或者代码块加锁&#xff0c;当它锁定一个方法或者一个代码块的时候&#xff…

Selenium(3)

练习1&#xff1a;Ecshop  录制登录后退出业务  打开系统  存储页面的标题     a.点击"登录"按钮     b.输入用户名&#xff1a;testing      存储输入的用户名     c.输入密码&#xff1a;123456     d.点击"立即登录"按钮 …

php 爬虫_Rad爬虫结合W13Scan扫描器挖掘漏洞

一、背景这几天一直在研究W13Scan漏洞扫描器&#xff0c;因为对Python不是太熟悉&#xff0c;所以进度有点慢&#xff0c;一直没看懂怎么将代理请求的数据转发到扫描队列中去&#xff0c;决定先熟悉熟悉这个功能再说&#xff1b;Rad爬虫最近比较火&#xff0c;于是就是就选择它…

Python 爬取网页HTML代码

#/usr/bin/env python #-*- coding:utf-8 -*-import urllib2 import sys import chardetreq urllib2.Request("http://tycool.top/") content urllib2.urlopen(req).read() typeEncode sys.getfilesystemencoding()##系统默认编码 infoencode chardet.detect(con…

区块链兼容以太坊智能合约

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 引言 随着区块链技术以及应用的普及&#xff0c;越来越多的区块链出现在大众视野中。由于区块链技术的开源特性&#xff0c;任何公司和个人都可以…

Linux常用命令--网终设置

1、把自己&#xff08;sa&#xff09;添加到sudoers配置文件中&#xff0c;以便于获取权限 vim /etc/sudoers 编辑文件&#xff08;部分centOS版本没有vim命令&#xff0c;则用vi即可&#xff09; 找到【root ALL(ALL) ALL】语句&#xff0c;在下面添加&#xff1a; sa ALL…

python示例异常处理与程序调试_笔记:Python异常处理与程序调试

Python异常处理与程序调试Python提供了强大的异常处理机制&#xff0c;通过捕获异常可以提高程序的健壮性。异常处理还具有释放对象&#xff0c;中止循环的运行等作用。在程序运行的过程中&#xff0c;如果发生了错误&#xff0c;可以返回事先约定的一个错误代码。"try...…

js传入参数为字符串问题

示例&#xff1a; var device_mac"11qweq234ert";//第一种方式会报错&#xff1a;Onclick SyntaxError: identifier starts immediately after numeric literal&#xff0c;数字后面紧跟着字符这种写法只有device_mac是数字的时候是正确的。传入的为字符串则应该使用…

区块链热度背后的资本市场

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 进入2018年之后大家对于加密数字货币以及区块链等话题都各自有各自的意见和想法&#xff0c;很多人觉得区块链技术和加密数字货币是泡沫&#xff…

袋鼠过河(动态规划)

题目描述 一只袋鼠要从河这边跳到河对岸&#xff0c;河很宽&#xff0c;但是河中间打了很多桩子&#xff0c;每隔一米就有一个&#xff0c;每个桩子上都有一个弹簧&#xff0c;袋鼠跳到弹簧上就可以跳的更远。每个弹簧力量不同&#xff0c;用一个数字代表它的力量&#xff0c;如…

jenkins-svn配置

转载于:https://www.cnblogs.com/caer/p/5924337.html

python查看所有异常_如何获取python异常发生的实际行号?

如果你想按你描述的那样做from functools import wrapsimport sys, os, tracebackdef catch_exceptions(function):wraps(function)def decorator(*args, **kwargs):try:return function(*args, **kwargs)except Exception as e:exc_type, exc_obj, exc_tb sys.exc_info()prin…

区块链从一夜暴富到一夜暴“负”的辛酸史

3.15打假日&#xff0c;打假虽然年年有&#xff0c;但与往年有别的是&#xff0c;今年区块连技术得到了诸多重视以及初步发展&#xff0c;一些带有诈骗性质的数字资产交易所在用血腥的方式不断收割着更低层级的用户&#xff0c;而这些平台的受害者&#xff0c;却往往得不到任何…

iOS消息转发

消息转发是一种功能强大的技术&#xff0c;可以大大增加Objective-C的表现力。什么是消息转发&#xff1f;简而言之&#xff0c;它允许未知的消息被困住并作出反应。换句话说&#xff0c;无论何时发送未知消息&#xff0c;它​​都会以一个很好的包发送到您的代码中&#xff0c…

python参数类型限定_python限定方法参数类型、返回值类型、变量类型等|python3教程|python入门|python教程...

https://www.xin3721.com/eschool/python.htmltyping模块的作用自python3.5开始&#xff0c;PEP484为python引入了类型注解(type hints)类型检查&#xff0c;防止运行时出现参数和返回值类型、变量类型不符合。作为开发文档附加说明&#xff0c;方便使用者调用时传入和返回参数…

CentOS VMware 配置IP小结 静态 配置 桥接 NAT

系统启动后可先ping下外网或局域网内其它机器。如果配置虚拟机时选择的NAT上网方式&#xff0c;后面需要配置固定IP&#xff0c;请先参见VMware NAT方式下设置静态IP获得可用的IP范围和网关等信息。先将ifcfg-eth0备份到home目录下&#xff0c;不要放在与它同一目录下&#xff…

区块链简史:解读这场技术革命的前世今生

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 真格基金徐小平的一个“内部讲话”被泄露&#xff0c;揭开了创投圈对区块链的新一轮热衷。 在这份微信群的“内部讲话”中&#xff0c;徐小平把区块…

IncDec Sequence(codevs 2098)

题目描述 Description 给定一个长度为n的数列{a1,a2...an}&#xff0c;每次可以选择一个区间[l,r]&#xff0c;使这个区间内的数都加一或者都减一。  问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。 输入描述 Input…

C++ 中set

set特点&#xff1a; 所有元素不会重复&#xff0c;重复插入已经有的新值无效&#xff1b;所有元素按顺序排列&#xff1b;unordered_set除外键和值相同&#xff0c;所以set中的值是不可更改的set的各成员函数列表如下: 1.begin()--返回指向第一个元素的迭代器 // 如果当前容器…

python自动排课表_【python-leetcode210-拓扑排序】课程表Ⅱ

现在你总共有 n 门课需要选&#xff0c;记为 0 到 n-1。在选修某些课程之前需要一些先修课程。 例如&#xff0c;想要学习课程 0 &#xff0c;你需要先完成课程 1 &#xff0c;我们用一个匹配来表示他们: [0,1]给定课程总量以及它们的先决条件&#xff0c;返回你为了学完所有课…