发布时间:2024-12-23 02:24:24
Golang并发的核心概念是Goroutine,它是一种轻量级的执行单元。与传统的线程相比,Goroutine的创建和销毁代价非常低。开发者可以通过关键字"go"来启动一个Goroutine,并在其后紧跟需要执行的函数。以下是一个简单的例子:
``` func main() { go hello() fmt.Println("This is main goroutine") time.Sleep(1 * time.Second) } func hello() { fmt.Println("Hello from Goroutine") } ``` 在上面的例子中,主goroutine通过调用`go hello()`启动了一个新的Goroutine,该Goroutine会打印一条"Hello from Goroutine"的消息。同时,主goroutine继续执行并打印一条"This is main goroutine"的消息。由于新的Goroutine和主goroutine并发执行,因此输出的顺序是不确定的。无缓冲的通道是同步的,即发送和接收操作是阻塞的。当发送者尝试向无缓冲通道发送数据时,如果没有接收者等待接收数据,发送操作将被阻塞,直到有接收者可用。同样,当接收者尝试从无缓冲通道接收数据时,如果没有发送者发送数据,接收操作将被阻塞,直到有发送者发送数据。
``` func main() { ch := make(chan int) go sendData(ch) fmt.Println(<-ch) } func sendData(ch chan int) { ch <- 10 } ``` 在上面的例子中,我们创建了一个无缓冲通道`ch`。然后我们启动了一个新的Goroutine,并将通道作为参数传递给`sendData`函数。在`sendData`函数中,我们向通道发送了一个值为10的数据。而在主goroutine中,我们通过`<-ch`接收通道中的数据,并打印出来。由于无缓冲通道是同步的,因此`fmt.Println(<-ch)`语句将一直阻塞,直到`sendData`函数发送了数据。互斥锁是一种用于保护共享资源的机制。在任意时刻,一个互斥锁只能被一个Goroutine所持有。当一个Goroutine获取到互斥锁后,其他Goroutine将无法获取该互斥锁,直到持有者释放锁为止。
``` var mutex sync.Mutex var balance int func main() { go deposit(100) go withdraw(50) time.Sleep(1 * time.Second) fmt.Println(balance) } func deposit(amount int) { mutex.Lock() defer mutex.Unlock() balance += amount } func withdraw(amount int) { mutex.Lock() defer mutex.Unlock() balance -= amount } ``` 在上面的例子中,我们使用互斥锁来保护共享变量`balance`。在`deposit`和`withdraw`函数中,我们分别通过调用`mutex.Lock()`来获取互斥锁,并通过`defer mutex.Unlock()`在函数结束时释放锁。这样,只有一个Goroutine能够同时执行`deposit`或`withdraw`函数,从而保证了对共享变量的安全访问。比如,Golang标准库中的`sync`包提供了`WaitGroup`、`Once`、`Cond`等类型,用于解决并发编程中的一些常见问题。此外,还有一些第三方库,如`go-smart-routines`和`pool`等,可以帮助开发者更好地管理和优化Goroutine。