Jul
4
课程结束了,记录一下 Level 7 用到的这些 TED 课程,感觉还不错。
* Level 7
** Unit 1
*** Part 1
On Procrastination
https://www.ted.com/talks/tim_urban_inside_the_mind_of_a_master_procrastinator/transcript
*** Part 2
How Leaders Inspire Us
https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action/transcript
*** Part 3
On Endurance
https://www.ted.com/talks/david_blaine_how_i_held_my_breath_for_17_min/transcript
** Unit 2
*** Part 1
Never Ever Give Up
https://www.ted.com/talks/diana_nyad_never_ever_give_up/transcript
*** Part 2
The Boiling River
https://www.ted.com/talks/andres_ruzo_the_mythical_boiling_river_of_the_amazon/transcript
*** Part 3
On Machine Intelligence
https://www.ted.com/talks/zeynep_tufekci_machine_intelligence_makes_human_morals_more_important/transcript
** Unit 3
*** Part 1
Being a Global Citizen
https://www.ted.com/talks/hugh_evans_what_does_it_mean_to_be_a_citizen_of_the_world/transcript
*** Part 2
On Reading Minds
https://www.ted.com/talks/rebecca_saxe_how_brains_make_moral_judgments/transcript
*** Part 3
David and Goliath
https://www.ted.com/talks/malcolm_gladwell_the_unheard_story_of_david_and_goliath/transcript
* Level 8
** Unit 1
*** Part 1
The Math of Love
https://www.ted.com/talks/hannah_fry_the_mathematics_of_love/transcript
* Level 7
** Unit 1
*** Part 1
On Procrastination
https://www.ted.com/talks/tim_urban_inside_the_mind_of_a_master_procrastinator/transcript
*** Part 2
How Leaders Inspire Us
https://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action/transcript
*** Part 3
On Endurance
https://www.ted.com/talks/david_blaine_how_i_held_my_breath_for_17_min/transcript
** Unit 2
*** Part 1
Never Ever Give Up
https://www.ted.com/talks/diana_nyad_never_ever_give_up/transcript
*** Part 2
The Boiling River
https://www.ted.com/talks/andres_ruzo_the_mythical_boiling_river_of_the_amazon/transcript
*** Part 3
On Machine Intelligence
https://www.ted.com/talks/zeynep_tufekci_machine_intelligence_makes_human_morals_more_important/transcript
** Unit 3
*** Part 1
Being a Global Citizen
https://www.ted.com/talks/hugh_evans_what_does_it_mean_to_be_a_citizen_of_the_world/transcript
*** Part 2
On Reading Minds
https://www.ted.com/talks/rebecca_saxe_how_brains_make_moral_judgments/transcript
*** Part 3
David and Goliath
https://www.ted.com/talks/malcolm_gladwell_the_unheard_story_of_david_and_goliath/transcript
* Level 8
** Unit 1
*** Part 1
The Math of Love
https://www.ted.com/talks/hannah_fry_the_mathematics_of_love/transcript
Jul
2
线上服务Panic,部分日志如下
放狗搜了一下:math.Rand is not safe for concurrent use
from: https://github.com/golang/go/issues/3611
这个 issue 的 4 楼还提到 "top-level functions like strings.Split or fmt.Printf or rand.Int63 may be called from any goroutine at any time"
翻了一下源码,rand.Int() 用是自带 lock 的 globalRand 对象
看了下调用代码,之前的实现为了避免多个 goroutine 竞争同一个锁,所以 new 了一个 rand.Rand 对象,但没考虑到这个对象不支持并发。
最终的解决方案,是实现了一个 safeRander 。
具体代码不适合贴,核心逻辑是初始化 N 个 rand.Rand 对象和对应的 N 个锁,以及一个 index,每次调用 Int() 时,先 atomic.AddUint32(&index, 1) % N,加上对应的锁,再用对应的 rand.Rand 对象。
这样只要并发使用的goroutine不超过N个,就不会出现竞争;就算超过,竞争出现的频率也大幅减少了,而且也可以通过增加 N 来优化。
引用
err: runtime error: index out of range
Traceback:
goroutine 19209941 [running]:
...
panic(0x191d0e0, 0x2e078d0)
/usr/local/go/src/runtime/panic.go:502 +0x229
math/rand.(*rngSource).Uint64(...)
/usr/local/go/src/math/rand/rng.go:246
math/rand.(*rngSource).Int63(0xc438bb2a00, 0x0)
/usr/local/go/src/math/rand/rng.go:231 +0x8a
math/rand.(*Rand).Int63(0xc4279b3a70, 0x0)
/usr/local/go/src/math/rand/rand.go:82 +0x33
math/rand.(*Rand).Int(0xc4279b3a70, 0x0)
/usr/local/go/src/math/rand/rand.go:100 +0x2b
...
Traceback:
goroutine 19209941 [running]:
...
panic(0x191d0e0, 0x2e078d0)
/usr/local/go/src/runtime/panic.go:502 +0x229
math/rand.(*rngSource).Uint64(...)
/usr/local/go/src/math/rand/rng.go:246
math/rand.(*rngSource).Int63(0xc438bb2a00, 0x0)
/usr/local/go/src/math/rand/rng.go:231 +0x8a
math/rand.(*Rand).Int63(0xc4279b3a70, 0x0)
/usr/local/go/src/math/rand/rand.go:82 +0x33
math/rand.(*Rand).Int(0xc4279b3a70, 0x0)
/usr/local/go/src/math/rand/rand.go:100 +0x2b
...
放狗搜了一下:math.Rand is not safe for concurrent use
from: https://github.com/golang/go/issues/3611
这个 issue 的 4 楼还提到 "top-level functions like strings.Split or fmt.Printf or rand.Int63 may be called from any goroutine at any time"
翻了一下源码,rand.Int() 用是自带 lock 的 globalRand 对象
func Int() int { return globalRand.Int() }
...
var globalRand = New(&lockedSource{src: NewSource(1).(Source64)})
...
type lockedSource struct {
lk sync.Mutex
src Source64
}
...
func (r *lockedSource) Uint64() (n uint64) {
r.lk.Lock()
n = r.src.Uint64()
r.lk.Unlock()
return
}
...
var globalRand = New(&lockedSource{src: NewSource(1).(Source64)})
...
type lockedSource struct {
lk sync.Mutex
src Source64
}
...
func (r *lockedSource) Uint64() (n uint64) {
r.lk.Lock()
n = r.src.Uint64()
r.lk.Unlock()
return
}
看了下调用代码,之前的实现为了避免多个 goroutine 竞争同一个锁,所以 new 了一个 rand.Rand 对象,但没考虑到这个对象不支持并发。
最终的解决方案,是实现了一个 safeRander 。
具体代码不适合贴,核心逻辑是初始化 N 个 rand.Rand 对象和对应的 N 个锁,以及一个 index,每次调用 Int() 时,先 atomic.AddUint32(&index, 1) % N,加上对应的锁,再用对应的 rand.Rand 对象。
这样只要并发使用的goroutine不超过N个,就不会出现竞争;就算超过,竞争出现的频率也大幅减少了,而且也可以通过增加 N 来优化。