当前位置:网站首页>n++也不靠谱
n++也不靠谱
2022-07-04 12:34:00 【小锟哥哥】

今天小明又去面试了,又被问了一个奇怪的面试题:
n := 0
for i := 0; i < 1000000; i++ {
go func() {
n++
}()
}
fmt.Println(n)
到你思考的时间了,输出啥结果呢?
小明思考了许久,给出了他的回答:不知道,然后面试官就告诉他:你通过了。
是不是有点离谱,没错,这个代码的结果就是不知道,每次执行的结果都不一样,全看 cpu 咋调度。
且听我来给客官慢慢道来。
一、最开始的原型
我们根据面试代码,往回滚一点,看下这样的代码:
n := 0
for i := 0; i < 1000000; i++ {
func() {
n++
}()
}
fmt.Println(n)
我们把协程拿掉,现在的结果是不是就很好知道了,没错就是循环的次数 1000000。
二、里面的坑
我们再回到面试的代码,这里面其实有两个坑:
第一个坑:他没加协程等待,所以很可能一扫而过,还没循环几次主程序就结束了,甚至是一次循环都没做就退出了。
但是在面试中,一般不提这个坑,这不是面试的重点,当然你也可以提一下。
第二个坑就是面试的重点了:
在不考虑主线程提前退出的问题,就是加入协程后,n++ 的结果不准确了。
为什么呢?
因为 n++ 并不是原子的,他要完成 n++ 的操作他需要做三步:
从内存里面取出值 执行 +1 操作 赋值回去
因为他不是原子的,所以很可能在你取值的时候别的线层也在取值,也在进行计算,最后赋值时就会被覆盖,从而出现随机不可预算的结果。
三、该怎么保证结果呢?
因为 n++ 不是原子的,如果我们要让他变原子,常见的操作有两种:
1、加锁
首先我们为了保证他能把循环执行完毕,需要加个 wait:
wg := sync.WaitGroup{}
n := 0
for i := 0; i < 1000000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
n++ //不是原子的 1、从内存读出 2、n++ 3、赋值
}()
}
wg.Wait()
fmt.Println(n)
这样就能让他执行完毕了,再加入我们的线层锁:
wg := sync.WaitGroup{}
locker := sync.Mutex{}
n := 0
for i := 0; i < 1000000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// 锁
defer locker.Unlock()
locker.Lock()
n++ //不是原子的 1、从内存读出 2、n++ 3、赋值
}()
}
wg.Wait()
fmt.Println(n)
这样执行的结果,每次都是执行的次数了。
2、使用 atomic
我们偶尔还会使用 atomic 包来处理这类操作,但是也有一定局限,他支持的数据类型有限。
直接上代码:
var n int32 = 0
for i := 0; i < 1000000; i++ {
func() {
atomic.AddInt32(&n, 1) //原子操作
}()
}
fmt.Println(n)
这里我们把 n 变成了 int32 类型,这样的运行结果也能保证是循环的次数。
边栏推荐
- Detailed explanation of mt4api documentary and foreign exchange API documentary interfaces
- C language: find the length of string
- BackgroundWorker用法示例
- Argminer: a pytorch package for processing, enhancing, training, and reasoning argument mining datasets
- Fly tutorial 02 advanced functions of elevatedbutton (tutorial includes source code) (tutorial includes source code)
- Unity performance optimization reading notes - Introduction (1)
- vim 出现 Another program may be editing the same file. If this is the case 的解决方法
- Translation D29 (with AC code POJ 27:mode of sequence)
- Global and Chinese markets of digital PCR and real-time PCR 2022-2028: Research Report on technology, participants, trends, market size and share
- Azure solution: how can third-party tools call azure blob storage to store data?
猜你喜欢

PostgreSQL 9.1 soaring Road

Abnormal mode of ARM processor

0x15 string

Show recent errors only command /bin/sh failed with exit code 1

C fonctions linguistiques

Will the concept of "being integrated" become a new inflection point of the information and innovation industry?
![[leetcode] 96 and 95 (how to calculate all legal BST)](/img/d5/788c88064bce6a7c4499017908b3f2.jpg)
[leetcode] 96 and 95 (how to calculate all legal BST)

AI 绘画极简教程

A taste of node JS (V), detailed explanation of express module

MDK在头文件中使用预编译器时,#ifdef 无效的问题
随机推荐
Servlet learning notes
Is there an elegant way to remove nulls while transforming a Collection using Guava?
DVWA range exercise 4
[notes] in depth explanation of assets, resources and assetbundles
Concepts and theories related to distributed transactions
Azure solution: how can third-party tools call azure blob storage to store data?
C language: find the length of string
After installing vscode, the program runs (an include error is detected, please update the includepath, which has been solved for this translation unit (waveform curve is disabled) and (the source fil
[Android kotlin] lambda return statement and anonymous function
C语言函数
Openssl3.0 learning 20 provider KDF
C language function
Vit (vision transformer) principle and code elaboration
17.内存分区与分页
面试官:Redis 过期删除策略和内存淘汰策略有什么区别?
Ml and NLP are still developing rapidly in 2021. Deepmind scientists recently summarized 15 bright research directions in the past year. Come and see which direction is suitable for your new pit
强化学习-学习笔记1 | 基础概念
Global and Chinese market of piston rod 2022-2028: Research Report on technology, participants, trends, market size and share
Wechat video Number launches "creator traffic package"
[Yu Yue education] 233 pre school children's language education reference questions in the spring of 2019 of the National Open University