GO语言多线程实践-1

写在前面

其实不论是哪一种编程语言,在当下这种大数据的业务压力下,多线程都是重中之重。本文的一些关于go语言的多线程实践都是基于MIT6.824课程总结而来的。

多线程通信

使用channel通道

关于利用channel实现多线程通信的方法,在另外一篇博客中已经提及了,需要注意的主要是其可能造成的死锁问题,本文主要介绍下面这种多线程通信的方式。

使用全局变量+锁

其实这种方法与channel最大的不同就是,前者是go语言所独有的特性,因为其天然的可以集成多线程并发。这种方法在很多编程语言中都有,譬如Java中的使用volatile这种所有线程均可见的全局变量,再配合lock锁实现多线程协同。

在GO语言中,并未有专用的用于线程协同的全局变量,所有全局变量均可以担任这项职责。下面给出一个简单的实践场景需求。

实践场景

6.824课程中的lab2需要实现Raft共识算法。Raft公式算法有两个非常重要的过程:leader election以及log replicaed。在leader election流程中,一个节点可以有三个状态:follower、candidate、以及leader。当一个节点获得大多数投票之后,他需要告诉所有其他candidate节点我已当选,你们需要改变为follower节点。这就存在了一个多线程的实践场景:两个线程正常运行,在其中一个线程满足某种条件后,影响另外一个线程的退出或者执行状态。具体代码见下。

实践代码

package main

import (
	"sync"
	"time"
	"fmt"
)
var done bool
var mu sync.Mutex

func main() {
	time.Sleep(1 * time.Second)
	go dosome()
	time.Sleep(10 * time.Second)
	mu.Lock()
	done = true
	mu.Unlock()
	fmt.Println("cancelled")
	time.Sleep(2 * time.Second)
}

func dosome()  {
	for {
		if done {
			return
		}
		fmt.Println("tick")
		time.Sleep(1 * time.Second)
	}
}

可以看到,在main这个主线程中新开一个线程调用了dosome方法,dosome类似于心跳机制,每隔1s输出一个“tick”字符,前提是done变量为flase。而主线程在等待10s之后,将done变量设置为true,注意这里需要用lock锁住,保证线程安全(其实不需要,但是在更复杂的多线程环境中这是必不可少的)。当运行dosome方法的线程看到done变量为true之后,退出线程。主线程打印cancelled之后,等待2s,判断tick是否真的结束,然后退出。
具体运行结果见下:

tenris-MBP:src Sirius$ go run demo.go 
tick
tick
tick
tick
tick
tick
tick
tick
tick
tick
cancelled

可以看到正常输出10个tick以及一个cancelled。当然这是很简单的实践方式,后序会面临更加复杂的多线程并发场景。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值