go语言编程并发通信 go语言 并发

Go并发编程之美-CAS操作

摘要: 一、前言 go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中CAS操作 二、CAS操作 go中的Cas操作与java中类似,都是借用了CPU提供的原子性指令来实现。

成都创新互联公司专注于海安企业网站建设,响应式网站开发,商城开发。海安网站建设公司,为海安等地区提供建站服务。全流程定制网站建设,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务

go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中CAS操作

go中的Cas操作与java中类似,都是借用了CPU提供的原子性指令来实现。CAS操作修改共享变量时候不需要对共享变量加锁,而是通过类似乐观锁的方式进行检查,本质还是不断的占用CPU 资源换取加锁带来的开销(比如上下文切换开销)。下面一个例子使用CAS来实现计数器

go中CAS操作具有原子性,在解决多线程操作共享变量安全上可以有效的减少使用锁所带来的开销,但是这是使用cpu资源做交换的。

我简单列举了并发编程的大纲,需要详细的私信“555”~~

Go CSP并发模型

Go的CSP并发模型

Go实现了两种并发形式。第一种是大家普遍认知的:多线程共享内存。其实就是Java或者C++等语言中的多线程开发。另外一种是Go语言特有的,也是Go语言推荐的:CSP(communicating sequential processes)并发模型。

CSP 是 Communicating Sequential Process 的简称,中文可以叫做通信顺序进程,是一种并发编程模型,由 Tony Hoare 于 1977 年提出。简单来说,CSP 模型由并发执行的实体(线程或者进程)所组成,实体之间通过发送消息进行通信,这里发送消息时使用的就是通道,或者叫 channel。CSP 模型的关键是关注 channel,而不关注发送消息的实体。 Go 语言实现了 CSP 部分理论 。

“ 不要以共享内存的方式来通信,相反, 要通过通信来共享内存。”

Go的CSP并发模型,是通过 goroutine和channel 来实现的。

goroutine 是Go语言中并发的执行单位。其实就是协程。

channel是Go语言中各个并发结构体(goroutine)之前的通信机制。 通俗的讲,就是各个goroutine之间通信的”管道“,有点类似于Linux中的管道。

Channel

Goroutine

在 Go 中实现一个支持并发的 TCP 服务端

TCP 和 UDP 服务端随处可见,它们基于 TCP/IP 协议栈,通过网络为客户端提供服务。在这篇文章中,我将介绍如何使用 Go 语言开发一个用于返回随机数、支持并发的 TCP 服务端。对于每一个来自 TCP 客户端的连接,它都会启动一个新的 goroutine(轻量级线程)来处理相应的请求。

你可以在 GitHub 上找到本项目的源码:concTcp.go。

这个程序的主要逻辑在 handleConnection 函数中,具体实现如下:

在 main 函数的实现部分,每当 TCP 服务端收到 TCP 客户端的连接请求,它都会启动一个新的 goroutine 来为这个请求提供服务。

首先, main 确保程序至少有一个命令行参数。注意,现有代码并没有检查这个参数是否为有效的 TCP 端口号。不过,如果它是一个无效的 TCP 端口号, net.Listen 就会调用失败,并返回一个错误信息,类似下面这样:

net.Listen 函数用于告诉 Go 接受网络连接,因而承担了服务端的角色。它的返回值类型是 net.Conn ,后者实现了 io.Reader 和 io.Writer 接口。此外, main 函数中还调用了 rand.Seed 函数,用于初始化随机数生成器。最后, for 循环允许程序一直使用 Accept 函数来接受 TCP 客户端的连接请求,并以 goroutine 的方式来运行 handleConnection(c) 函数,处理客户端的后续请求。

net.Listen 函数的第一个参数定义了使用的网络类型,而第二个参数定义了服务端监听的地址和端口号。第一个参数的有效值为 tcp 、 tcp4 、 tcp6 、 udp 、 udp4 、 udp6 、 ip 、 ip4 、 ip6 、 Unix (Unix 套接字)、 Unixgram 和 Unixpacket ,其中: tcp4 、 udp4 和 ip4 只接受 IPv4 地址,而 tcp6 、 udp6 和 ip6 只接受 IPv6 地址。

concTCP.go 需要一个命令行参数,来指定监听的端口号。当它开始服务 TCP 客户端时,你会得到类似下面的输出:

netstat 的输出可以确认 congTCP.go 正在为多个 TCP 客户端提供服务,并且仍在继续监听建立连接的请求:

在上面输出中,最后一行显示了有一个进程正在监听 8001 端口,这意味着你可以继续连接 TCP 的 8001 端口。第一行和第二行显示了有一个已建立的 TCP 网络连接,它占用了 8001 和 62556 端口。相似地,第三行和第四行显示了有另一个已建立的 TCP 连接,它占用了 8001 和 62554 端口。

下面这张图片显示了 concTCP.go 在服务多个 TCP 客户端时的输出:

类似地,下面这张图片显示了两个 TCP 客户端的输出(使用了 nc 工具):

你可以在 维基百科上找到更多关于 nc (即 netcat )的信息。

现在,你学会了如何用大约 65 行 Go 代码来开发一个生成随机数、支持并发的 TCP 服务端,这真是太棒了!如果你想要让你的 TCP 服务端执行别的任务,只需要修改 handleConnection 函数即可。

via:

作者:Mihalis Tsoukalos选题:lkxed译者:lkxed校对:wxy


网站栏目:go语言编程并发通信 go语言 并发
网页路径:http://hbruida.cn/article/dosihhc.html