我是码客
2022-11-05
unbuffered := make(chan int) a := <- unbuffered // 阻塞 unbuffered := make(chan int) // 1) 阻塞 a := <- unbuffered // 2) 阻塞 unbuffered <- // 3) 同步 go func() { <-unbuffered }() unbuffered <-
buffered := make(chan int, ) // 4) 阻塞 a := <- buffered // 5) 不阻塞 buffered <- // 6) buffer满,阻塞 buffered <-
c := make(chan int) close(c) fmt.Println(<-c) //接收并输出chan类型的零值,这里int是0
func TryReceive(c <-chan int) (data int, more, ok bool) { select { case data, more = <- c: return data, more, true } default: return , true, false }
func TryReceiveWithTimeout(c <-chan int, duration time.Duration) (data int, more, ok bool) { select { case data, more = <-c: return data, more, true case <- time.After(duration): return , true, false
}
}
package main import (
"fmt"
"runtime"
"time"
) var i int64 = func main() {
runtime.GOMAXPROCS()
go func() {
for {
fmt.Println("i is", i)
time.Sleep(time.Second)
}
}() for {
i +=
}
}
================== WARNING: DATA RACE Read at 0x00000121e848 by goroutine : main.main.func1() /Users/saas/src/awesomeProject/datarace/main.go: +0x3e Previous write at 0x00000121e848 by main goroutine: main.main() /Users/saas/src/awesomeProject/datarace/main.go: +0x7b Goroutine (running) created at: main.main() /Users/saas/src/awesomeProject/datarace/main.go: +0x4f ==================
package main import (
"fmt"
"runtime"
"sync"
"time"
) var i int64 = func main() {
runtime.GOMAXPROCS()
var m sync.Mutex
go func() {
for {
m.Lock()
fmt.Println("i is", i)
m.Unlock()
time.Sleep(time.Second)
}
}() for {
m.Lock()
i +=
m.Unlock()
}
}
package main import (
"fmt"
"runtime"
"time"
) var i int64 = func main() {
runtime.GOMAXPROCS()
c := make(chan int64)
go func() {
for {
fmt.Println("i is", <-c)
time.Sleep(time.Second)
}
}() for {
i +=
c<-i
}
}
type Spinlock struct { state *int32 } const free = int32() func (l *Spinlock) Lock() { for !atomic.CompareAndSwapInt32(l.state, free, ) { //如果state等于0就赋值为42 runtime.Gosched() //让出CPU } } func (l *Spinlock) Unlock(){ atomic.StoreInt32(l.state, free) // 所有操作state变量的操作都应该是原子的 }
func restore(repos []string) error {
errChan := make(chan error, )
sem := make(chan int, ) // four jobs at once
var wg sync.WaitGroup
wg.Add(len(repos))
for _, repo := range repos {
sem <-
go func() {
defer func() {
wg.Done()
<- sem
}()
if err := fetch(repo); err != nil {
errChan <- err
}
}()
}
wg.Wait()
close(sem)
close(errChan)
return <- errChan
}
func restore(repos []string) error {
errChan := make(chan error, )
sem := make(chan int, ) // four jobs at once
var wg sync.WaitGroup
wg.Add(len(repos))
for _, repo := range repos {
go worker(repo, sem, &wg, errChan)
}
wg.Wait()
close(errChan)
return <- errChan
} Func worker(repo string, sem chan int, wg *sync.WaitGroup, errChan chan err) {
defer wg.Done()
sem <-
if err := fetch(repo); err != nil {
select {
case errChan <- err:
// we are the first worker to fail
default:
// some other failure has already happened, drop this one
}
}
<- sem
}