golang中channel什么时候会阻塞

2024-08-21 13:28
文章标签 golang channel 阻塞

本文主要是介绍golang中channel什么时候会阻塞,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在 Go 中,通道(channel)会在以下情况下阻塞:

1. 发送操作阻塞

  • 无缓冲通道: 当你向无缓冲通道发送数据时,如果没有其他 goroutine 读取数据,发送操作将阻塞。

    ch := make(chan int) // 无缓冲通道
    ch <- 1 // 阻塞,直到有接收者
    
  • 缓冲通道已满: 当缓冲通道的缓冲区已满时,尝试发送数据将阻塞,直到有空间可用。

    ch := make(chan int, 2) // 缓冲通道,大小为 2
    ch <- 1
    ch <- 2
    // ch <- 3 // 阻塞,直到有人接收
    

2. 接收操作阻塞

  • 无缓冲通道: 当你从无缓冲通道接收数据时,如果没有其他 goroutine 发送数据,接收操作将阻塞。

    ch := make(chan int) // 无缓冲通道
    val := <-ch // 阻塞,直到有人发送
    
  • 缓冲通道为空: 当尝试从缓冲通道接收数据时,如果通道为空,接收操作将阻塞,直到有数据可用。

    ch := make(chan int, 2) // 缓冲通道
    // ch <- 1
    // val := <-ch // 阻塞,直到有人发送数据
    

3. select 语句阻塞

  • select 会阻塞,直到其中一个 case 可执行。如果所有的 case 都不可执行(例如,所有的通道都没有数据可读或没有空间可写),则 select 将阻塞。

    select {
    case msg := <-ch1: // 如果 ch1 没有数据则阻塞fmt.Println(msg)
    case ch2 <- 2: // 如果 ch2 满则阻塞fmt.Println("Sent to ch2")
    }
    

4. 避免阻塞

  • 使用 default: 在 select 中添加 default 分支可以避免阻塞。

    select {
    case msg := <-ch:fmt.Println(msg)
    default:fmt.Println("No messages received")
    }
    

总结

通道的阻塞机制是 Go 实现并发的重要特性,它确保了数据的安全传递和同步。在使用通道时,理解何时会阻塞对于编写高效的并发程序至关重要。

这篇关于golang中channel什么时候会阻塞的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093289

相关文章

springboot体会BIO(阻塞式IO)

使用springboot体会阻塞式IO 大致的思路为: 创建一个socket服务端,监听socket通道,并打印出socket通道中的内容。 创建两个socket客户端,向socket服务端写入消息。 1.创建服务端 public class RedisServer {public static void main(String[] args) throws IOException {

多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信

目录 多路转接之select 引入 介绍 fd_set 函数原型 nfds readfds / writefds / exceptfds readfds  总结  fd_set操作接口  timeout timevalue 结构体 传入值 返回值 代码 注意点 -- 调用函数 select的参数填充  获取新连接 注意点 -- 通信时的调用函数 添加新fd到

Go Channel的实现

channel作为goroutine间通信和同步的重要途径,是Go runtime层实现CSP并发模型重要的成员。在不理解底层实现时,经常在使用中对channe相关语法的表现感到疑惑,尤其是select case的行为。因此在了解channel的应用前先看一眼channel的实现。 Channel内存布局 channel是go的内置类型,它可以被存储到变量中,可以作为函数的参数或返回值,它在r

Golang进程权限调度包runtime

关于 runtime 包几个方法: Gosched:让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,因此当前线程未来会继续执行GOMAXPROCS:设置最大的可同时使用的 CPU 核数Goexit:退出当前 goroutine(但是defer语句会照常执行)NumGoroutine:返回正在执行和排队的任务总数GOOS:目标操作系统NumCPU:返回当前系统的 CPU 核数量 p

Golang 网络爬虫框架gocolly/colly(五)

gcocolly+goquery可以非常好地抓取HTML页面中的数据,但碰到页面是由Javascript动态生成时,用goquery就显得捉襟见肘了。解决方法有很多种: 一,最笨拙但有效的方法是字符串处理,go语言string底层对应字节数组,复制任何长度的字符串的开销都很低廉,搜索性能比较高; 二,利用正则表达式,要提取的数据往往有明显的特征,所以正则表达式写起来比较简单,不必非常严谨; 三,使

Golang网络爬虫框架gocolly/colly(四)

爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟。回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫,那时由于项目需要,要访问各大国际社交网站,Facebook,myspace,filcker,youtube等等,国际上叫得上名字的社交网站都爬过,大部分网站提供restful api,有些功能没有api,就只能用http抓包工具分析协议,自己爬;国内的优酷、

Golang网络爬虫框架gocolly/colly(三)

熟悉了《Golang 网络爬虫框架gocolly/colly 一》和《Golang 网络爬虫框架gocolly/colly 二》之后就可以在网络上爬取大部分数据了。本文接下来将爬取中证指数有限公司提供的行业市盈率。(http://www.csindex.com.cn/zh-CN/downloads/industry-price-earnings-ratio) 定义数据结构体: type Zhj

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.