c语言编程笔录

首页 >   > 笔记大全

笔记大全

golang怎么并发

更新时间:2023-09-09

引言

并发是Go语言的本质特性之一,被广泛用于处理并行和分布式系统中。Go语言使用协程(或者叫Goroutine)和通道(channel)来实现并发。本文将以这两种方式为主,介绍golang中如何实现并发。

协程(Goroutine)

Goroutine是Golang提供的一种轻量级线程,它和操作系统线程不同,它是由Go语言的运行时负责调度的。在编写代码时,我们只需要定义一个函数并在函数调用前加上"go"关键字,即可创建一个新的协程。

	func worker(i int) {
		fmt.Printf("Worker %d starting\n", i)
		time.Sleep(time.Second)
		fmt.Printf("Worker %d done\n", i)
	}
	func main() {
		for i := 0; i < 5; i++ {
			go worker(i)
		}
		time.Sleep(time.Second * 2)
		fmt.Println("Main function exiting...")
	}

在上面的例子中,我们定义了一个"worker"函数,它会输出一些信息,休眠1秒钟,然后再输出另一些信息。在"main"函数中,我们使用一个循环语句创建了5个协程,每个协程都会调用"worker"函数。最后等待2秒钟,使程序有足够的时间执行完所有的协程,并打印"Main function exiting..."。

通道(channel)

通道是Golang提供的一种用于并发程序之间通信的方式。通道在多协程之间传递数据,保证了并发竞争的安全性。操作通道的关键字是"chan",用于定义通道的数据类型。使用通道时,需要注意的一点是:通道发送操作和接收操作是阻塞的。只有在有对应的接收方或发送方时,通道才会释放它们。我们可以使用"select"语句来避免通道阻塞,与接收方同步进行。

	func worker(id int, jobs <-chan int, results chan<- int) {
		for j := range jobs {
			fmt.Printf("Worker %d started job %d\n", id, j)
			time.Sleep(time.Second)
			fmt.Printf("Worker %d finished job %d\n", id, j)
			results <- j * 2
		}
	} 
	func main() {
		jobs := make(chan int, 100)
		results := make(chan int, 100)

		for w := 1; w <= 3; w++ {
			go worker(w, jobs, results)
		}

		for j := 1; j <= 9; j++ {
			jobs <- j
		}
		close(jobs)

		for a := 1; a <= 9; a++ {
			<-results
		}
	}

在上面的例子中,我们定义了一个"worker"函数,它会从通道"jobs"中获取一些工作,然后处理这些工作,将处理结果发送到通道"results"中。"main"函数则创建了3个协程并在循环内向通道"jobs"中发送了9个工作任务。我们注意到在最后一个循环中执行了9次"<-results"操作,这个操作会立即阻塞直到有结果被发送到通道"results"中。这样可以确保所有的工作都被正确地处理,并且每个工作都有一个对应的结果。

并发安全与锁

并发安全是指在多线程或多协程之间共享资源时,保证资源被访问时的正确性和同步。在Go语言中,可以使用sync包中的互斥锁实现对共享资源的保护。互斥锁是一种并发控制机制,它保证同一时间只有一个协程可以访问共享资源。

	var mutex sync.Mutex
	var balance int
	func Deposit(amount int) {
		mutex.Lock()
		balance += amount
		mutex.Unlock()
	}
	func Balance() int {
		mutex.Lock()
		b := balance
		mutex.Unlock()
		return b
	}

在上面的例子中,我们定义了一个互斥锁"mutex"和一个变量"balance",用于保护对"balance"变量的读写。在"Deposit"和"Balance"函数中,我们使用了"mutex.Lock"和"mutex.Unlock"方法来保护对"balance"变量的读写,从而确保多个协程访问"balance"变量时的并发安全性。