GoLang之Concurrency协程goroutine使用方法

本文介绍Go语言中goroutine的使用方法及并发编程实践。通过示例代码展示如何利用goroutine实现并行任务,以及如何借助通道(channel)进行goroutine间的通信与同步。

2013-12-08 wcdj


在go语言中,使用goroutine(a lightweight thread managed by the Go runtime)来实现并发程序。

go f(x, y, z)

starts a new goroutine running

f(x, y, z)

The evaluation of f, x, y, and z happens in the current goroutine and the execution off happens in the new goroutine.

Goroutines run in the same address space, so access to shared memory must be synchronized. Thesync package provides useful primitives, although you won't need them much in Go as there are other primitives. (See the next slide, Channels.http://tour.golang.org/#64)


简单的测试用例:

package main

import (
	"fmt"
	"time"
)

func main() {

	// A goroutine is a lightweight thread managed by the Go runtime
	//  Goroutines run in the same address space, so access to shared memory must be synchronized
	go say("world")
	say("hello")

	fmt.Println("---------------1")

	a := []int{7, 2, 8, -9, 4, 0}

	// Channels are a typed conduit through which you can send and receive values with the channel operator, <-
	// By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables
	c := make(chan int)
	go sum(a[:len(a)/2], c)
	go sum(a[len(a)/2:], c)
	x, y := <-c, <-c // receive from c

	fmt.Println(x, y, x+y)

	fmt.Println("---------------2")

	// Channels can be buffered. Provide the buffer length as the second argument to make to initialize a buffered channel
	c2 := make(chan int, 2)
	c2 <- 1
	c2 <- 2
	//c2 <- 3// error, the send buffer is full that will causes deadlock!
	fmt.Println(<-c2)
	fmt.Println(<-c2)
	//fmt.Println(<-c2)// error, the receive buffer is empty that will causes deadlock too!

	fmt.Println("---------------3")
	c3 := make(chan int, 10)
	go fibonacci(cap(c3), c3)
	for i := range c3 {
		fmt.Println(i)
	}

	fmt.Println("---------------4")
	c4 := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c4)
		}
		quit <- 0
	}()
	fibonacci2(c4, quit)

	fmt.Println("---------------5")
	// The default case in a select is run if no other case is ready
	// Use a default case to try a send or receive without blocking
	tick := time.Tick(100 * time.Millisecond)
	boom := time.After(500 * time.Millisecond)
	for {
		select {
		case <-tick:
			fmt.Println("tick. ")
		case <-boom:
			fmt.Println("BOOM!")
			return
		default:
			fmt.Println("    .")
			time.Sleep(50 * time.Millisecond)
		}
	}

}

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func sum(a []int, c chan int) {
	sum := 0
	for _, v := range a {
		sum += v
	}
	c <- sum // send sum to c
}

func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	// Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic
	// Another note: Channels aren't like files; you don't usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop
	close(c)
}

// The select statement lets a goroutine wait on multiple communication operations
// A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready
func fibonacci2(c, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case c <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("quit")
			return
		}
	}
}
/*
output:

hello
world
hello
world
hello
world
hello
world
hello
---------------1
world
17 -5 12
---------------2
1
2
---------------3
0
1
1
2
3
5
8
13
21
34
---------------4
0
1
1
2
3
5
8
13
21
34
quit
---------------5
    .
    .
tick. 
    .
    .
tick. 
    .
    .
tick. 
    .
    .
tick. 
    .
    .
BOOM!
*/






delphiASIO_mmzmagic本库是Boost ASIO for delphi的高效率稳定封装 做了8年多的DELPHI开发,还仍然在用D7,后续的DELPHI版本比如d2007,d2010还是非常很优秀的,有许多方便的功能和语法效率的改进。为啥不更换到新版本呢? 对于我来说究其原因还是因为通讯程序无法简单的做修改就移植到新版本上。 另外一个方面也是DELPHI本身没有较好的通讯库,INDY不稳定也不完善,不同版本也有些区别。开发起来四处抛异常的方式也让人很不爽。 研究了一些第三方通讯库,如ics系列dxsock系列,最后选择了dxsock,这样轻量级的库从稳定性还是易用性来说都比其它的要好用些。 不过这些库由于底层实现的方式都不能很好的支持大规模应用,由于后续支持的问题也不能支持DELPHI的新unicode版本。 C++由于有类似ACE、ASIO等等工业级的高性能稳定牛库的支持,c++的使用者们可以轻轻松松搞定很多难题而不用为并发连接数发愁。 为此经我研究决定封装底层基于IOCP(完成端口)实现的Boost::ASIO为DELPHI的底层通讯库,并且已经实现,delphi fans们大家有福啦 哈哈! 主要有以下几点好处: 1、支持大量并发( xp系统上测试可以支持到15000+的并发连接,付测试程序) 2、支持delphi的所有版本(d5以及以上版本都可以支持) 3、支持tcp服务端和客户端、异步通讯机制 4、在封装中自动高效处理粘包、异步通讯内存管理等较烦人的问题,也是容易导致不稳定的因素,提供外部使用的简明接口 5、最重要的是使用和开发都十分简单 :) FAQ: 我能用它做什么? 答:所有用到tcp通讯的地方你都可以用它。 用它封装的服务端或者客户端可以与其它控件或者是其它程序进行通讯吗? 答:可以,底层是标准tcp协议,不会有任何问题。 它有什么示例程序吗? 答:有专门的性能测试程序,也有远程数据库对象ADO版本以及UNIDAC版本的实际封装。 使用它是否需要支付费用?能否提供源代码? 答:完全免费使用,并且提供所有源码,我会做好后续更新为delphi的发展做点力所能及的贡献。 如果我对它进行了改进怎么联系作者? 答:QQ 22900104,马敏钊,邮箱 22900104@qq.com,QQ讨论群 15637473 欢迎加入讨论。 发布时客户端需要附带什么吗? 答:需要附带一个动态库“Svr_intf.dll”100k大小,由于是使用vs2005编译的boost库所以运行时机器上需要安装有微软的c++ vs2005运行库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值