一个select死锁问题

news2024/11/23 18:51:34

以下代码的输出结果:

func main() {
	var wg sync.WaitGroup
	foo := make(chan int)
	bar := make(chan int)
	wg.Add(1)
	go func() {
		defer wg.Done()
		select {
		case foo <- <-bar:
		default:
			println("default")
		}
	}()
	wg.Wait()
}

结果

在这里插入图片描述

解析

  1. 对于 select 语句,在进入该语句时,会按源码的顺序对每一个 case 子句进行求值:这个求值只针对发送或接收操作的额外表达式。将代码改为:

    func main() {
    	var wg sync.WaitGroup
    	foo := make(chan int)
    	bar := make(chan int)
    	wg.Add(1)
    	go func() {
    		defer wg.Done()
    		select {
    		case val:=<-bar:
    			foo<-val
    		// case foo <- <-bar:
    		default:
    			println("default")
    		}
    	}()
    	wg.Wait()
    }
    

    此时,正常输出:default

  2. 所以上述语句的理解就是:getVal()、<-input 和 getch() 等类似的操作会执行,导致死锁

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	ch := make(chan int)
    	go func() {
    		select {
    		case ch <- getVal(1):
    			fmt.Println("in first case")
    		case ch <- getVal(2):
    			fmt.Println("in second case")
    		default:
    			fmt.Println("default")
    		}
    	}()
    
    	fmt.Println("The val:", <-ch)
    }
    
    func getVal(i int) int {
    	fmt.Println("getVal, i=", i)
    	return i
    }
    

    无论 select 最终选择了哪个 case,getVal() 都会按照源码顺序执行:getVal(1) 和 getVal(2),必然输出:getVal, i= 1 | getVal, i= 2

相同问题

为什么每次都是输出一半数据,然后死锁?

package main

import (
	"fmt"
	"time"
)

func talk(msg string, sleep int) <-chan string {
	ch := make(chan string)
	go func() {
		for i := 0; i < 5; i++ {
			ch <- fmt.Sprintf("%s %d", msg, i)
			time.Sleep(time.Duration(sleep) * time.Millisecond)
		}
	}()
	return ch
}

func fanIn(input1, input2 <-chan string) <-chan string {
	ch := make(chan string)
	go func() {
		for {
			select {
			case ch <- <-input1:
			case ch <- <-input2:
			}
		}
	}()
	return ch
}

func main() {
	ch := fanIn(talk("A", 10), talk("B", 1000))
	for i := 0; i < 10; i++ {
		fmt.Printf("%q\n", <-ch)
	}
}
  1. 每次进入以下 select 语句时:<-input1 和 <-input2 都会执行,相应的值是:A x 和 B x(其中 x 是 0-5)。但每次 select 只会选择其中一个 case 执行,所以 <-input1 和 <-input2 的结果,必然有一个被丢弃了,也就是不会被写入 ch 中。因此,一共只会输出 5 次,另外 5 次结果丢掉了。
  2. 而 main 中循环 10 次,只获得 5 次结果,所以输出 5 次后,报死锁。

更多类似的问题

// ch 是一个 chan int;
// getVal() 返回 int
// input 是 chan int
// getch() 返回 chan int
select {
  case ch <- getVal():
  case ch <- <-input:
  case getch() <- 1:
  case <- getch():
}

最典型的问题

有内存泄露(传递给 time.After 的时间参数越大,泄露会越厉害)

PS: 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

func main()  {
    ch := make(chan int, 10)

    go func() {
        var i = 1
        for {
            i++
            ch <- i
        }
    }()

    for {
        select {
        case x := <- ch:
            println(x)
        case <- time.After(30 * time.Second):
            println(time.Now().Unix())
        }
    }
}
  1. 每次执行select都会执行一次time.After(30*time.Second)获取一个chan。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】进程信号

目录 一、什么是信号 二、信号产生的条件 1、键盘产生 2、进程异常 3、命令产生 4、软件条件 三、信号保存的方式 四、信号处理的方式 1、信号处理接口 2、信号处理时机 3、进程为什么要切换成为用户态才进行信号的捕获方法&#xff1f; 4、sigaction 五、可重入函…

Java+MySQL基于ssm的会议交接平台

随着社会竞争压力的不断加强,企事业单位内部的会议都在不断的增加,有效的会议可以提高企事业内部的沟通,更好的做出符合战略目标的决策,但是传统的会议交接有一定的问题存在,首先就是必须面对面进行传达,其次就是对任务的安排和执行没有很好的记录,为了改变这些情况,于是我们提…

信贷产品年终总结之贷后逾期分析

自本月月初疫情全面放开后&#xff0c;身边的朋友基本都阳了一遍&#xff0c;希望正在浏览本篇文章的读者您是还没阳过的幸运儿。另外&#xff0c;今天也是冬至了&#xff0c;祝各位读者身边健康&#xff0c;远离羊群&#xff01; 最近我们分享了信贷业务年终总结系列的前2篇文…

Python中转义字符是个啥

文章目录前言一、转义字符是什么&#xff1f;二、常见的转义字符有哪些&#xff1f;总结前言 昨天有粉丝问了我这个代码问题&#xff0c;如下图&#xff1a; 他很好奇代码都没有错误&#xff0c;怎么运行就报错&#xff0c;不知道有咩有小伙伴能看出问题在哪呢&#xff1f; 其…

Cookie 和 Session 的工作流程

文章目录1.Cookie1.什么是Cookie2.Cookie可以干嘛3.Cookie实现登陆逻辑的流程2.session1.session是什么2.session有什么用3.session的工作流程3.Cookie 和 session的区别(重点)1.Cookie 1.什么是Cookie Cookie中存储的是字符串,是浏览器在本地持久化保存数据的一种方案 通过点…

2023春招:Javaweb面试锦囊

cookie 和 session 的区别&#xff1f;&#xff08;必会&#xff09; 存储位置不同 cookie 存放在客户端电脑&#xff0c;是一个磁盘文件。Ie 浏览器是可以从文件夹中找到。session 是存放在服务器内存中的一个对象。 chrome 浏览器进行安全处理&#xff0c;只能通过浏览器找…

圣诞 HTML 代码汇总

文章目录Part.I 音效圣诞树Part.II 圣诞树小球Part.III 简笔圣诞树圣诞节快到了&#xff0c;在网上找了一些 html 代码&#xff0c;觉得挺有意思的&#xff0c;顺带分享一下~ Part.I 音效圣诞树 来源&#xff1a;https://blog.csdn.net/m0_73309780/article/details/128176149…

面临项目失控?四个维度应对项目进度优化【洞见2】

常见的对进度的管理的流程是制定进度目标&#xff0c;WBS工作任务拆解&#xff0c;任务的时间估算&#xff0c;然后执行监督。 有时候这样的过程就会出现的进度延迟&#xff0c;而针对进度的延迟&#xff0c;往往企业多选择是通过加班赶工来完成。 项目进度优化方案 但是如…

【第一章 Linux特点,结构,网路连接模式,Linux目录结构】

第一章 Linux特点&#xff0c;结构&#xff0c;网路连接模式&#xff0c;Linux目录结构 1.操作系统&#xff1a; 用于管理和控制计算机所有软、硬件资源的一组程序。 2. Linux特点总结&#xff1a; ① 开放性&#xff1b; ② 多用户&#xff1b; ③ 多任务&#xff1b; ④ 良好…

喇叭天线设计

电磁喇叭天线是最简单而常用的微波天线。它的主要优点是结构简单&#xff0c;馈电简便&#xff0c;便于控制主面波束宽度和增益&#xff0c;频率特性好且损耗较小。它由波导逐渐张开来形成&#xff0c;其作用是加强方向性&#xff0c;这与声学喇叭的原理相似。若主模TE10的矩形…

python爬虫爬取网页上的图片

目录 一&#xff1a;爬虫基础 二&#xff1a;安装html解析的python工具 三&#xff1a;爬取网页图片 一&#xff1a;爬虫基础 爬虫基本过程&#xff1a; 1.请求标头 headers 2.创建一个会话 requests.Session 3.确定请求的路径 4.根据路径获取网页资源(HTML文件) 5.解析html…

UG/NX二次开发Siemens官方NXOPEN实例解析—2.6 CreateNote

列文章目录 UG/NX二次开发Siemens官方NXOPEN实例解析—2.1 AssemblyViewer UG/NX二次开发Siemens官方NXOPEN实例解析—2.2 Selection UG/NX二次开发Siemens官方NXOPEN实例解析—2.3 Selection_UIStyler UG/NX二次开发Siemens官方NXOPEN实例解析—2.4 File2Points UG/NX二次…

【java随笔】面向对象思维

1.怎么建立面向对象的思维方式 &#xff08;1&#xff09;先整体&#xff0c;再局部 &#xff08;2&#xff09;先抽象&#xff0c;再具体 &#xff08;3&#xff09;能做什么&#xff0c;再怎么做 2.如何学习面向对象 &#xff08;1&#xff09;语法 &#xff08;2&#xff09…

执行docker restart [CONTAINER ID]命令时会把之前的参数都带上吗

我在搭建rocketmq时候&#xff0c;运行了好几个容器命令也比较长如下&#xff1a; # 启动 namesrv docker run -d -p 9876:9876 -v "D:/Program Files/rocketmq/namesrv/logs:/root/logs" -v "D:/Program Files/rocketmq/namesrv/store:/root/store" …

JAVA手机网站销售

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;

Hazelcast 在springboot下的使用集成

一、Hazelcast简介 Hazelcast是一款由Hazelcast公司开发的基于jvm环境的为各种应用提供分布式集群服务的分布式缓存解决方案。可以嵌入到java、c、.net等开发的产品中使用。其主要功能有&#xff1a; 提供了 Map、Queue、MultiMap、Set、List、Semaphore、Atomic 等接口的分布…

RocketMQ消费者没有成功消费消息的问题排查

背景 今天下游同事反馈&#xff0c;有一些以取消的订单库存还原异常了&#xff0c;导致部分商品库存没有还原。查日志发现没有收到还原消息&#xff0c;但是查看发送方是可以确认消息是已经发了的&#xff0c;那么是什么原因导致消费者没有收到&#xff0c;或者收到后没有处理消…

算法刷题打卡第53天:排序数组---希尔排序

排序数组 难度&#xff1a;中等 给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 示例 1&#xff1a; 输入&#xff1a;nums [5,2,3,1] 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;nums [5,1,1,2,0,0] 输出&#xff1a;[0,0,1,1,2,5]希尔排…

六、Buffer缓冲区和Stream流

Buffer —— 缓冲区 JavaScript 提供了大量对字符串的便捷操作&#xff0c;但没有读取或操作二进制数据流机制&#xff0c;而在Node.js中可以直接用Buffer类提供的构造函数创建Buffer实例&#xff0c;一个Buffer实例代表一个缓冲区&#xff0c;Buffer的缓冲区专门用于存放二进制…

全球「数字游民」现状,有人已经72岁了

近年来&#xff0c;“数字游民”在国内越来越流行&#xff0c;特别是受疫情的影响&#xff0c;很多人对这种工作生活方式越来越喜欢&#xff0c;也越来越习惯&#xff0c;在此之前&#xff0c;当你告诉别人你是一名“数字游民”时&#xff0c;大家通常会认为你是没有工作的无业…