这段代码的问题在于大部分情况是 ABC 按序输出的,但有时候 A 协程没有打印 A,结果变成了 BC
type cond struct{ sema1 int32 sema2 int32 } func (c *cond)printA(){ for { if c.sema1==0{ println("A") atomic.CompareAndSwapInt32(&c.sema1,0,1) } }
}
func (c *cond)printB(){ for { if c.sema1==1&& c.sema2==0{ println("B") atomic.CompareAndSwapInt32(&c.sema2,0,1) } } }
func (c *cond) printC(){ for { if c.sema2==1 { println("C") println("--------------------------------") atomic.CompareAndSwapInt32(&c.sema1, 1, 0) atomic.CompareAndSwapInt32(&c.sema2, 1, 0) } } }
func main() { var con =new (cond) con.sema1=0 con.sema2=0 go con.printC() go con.printB() go con.printA() time.Sleep(5*time.Second)
}
1
ldimple OP type cond struct{
sema1 int32 sema2 int32 } func (c *cond)printA(){ for { if c.sema1==0{ println("A") atomic.CompareAndSwapInt32(&c.sema1,0,1) } } } func (c *cond)printB(){ for { if c.sema1==1&& c.sema2==0{ println("B") atomic.CompareAndSwapInt32(&c.sema2,0,1) } } } func (c *cond) printC(){ for { if c.sema2==1 { println("C") println("--------------------------------") atomic.CompareAndSwapInt32(&c.sema1, 1, 0) atomic.CompareAndSwapInt32(&c.sema2, 1, 0) } } } func main() { var con =new (cond) con.sema1=0 con.sema2=0 go con.printC() go con.printB() go con.printA() time.Sleep(5*time.Second) } |
2
LoNeFong 2021-03-05 12:58:50 +08:00
友情提示, v 站支持 Markdown
|
3
sealingpp 2021-03-05 13:02:54 +08:00
|
6
Shakeitin 2021-03-05 13:20:17 +08:00
printC() 执行了 2 次 atomic 操作,但这两次操作的整体过程显然并不是原子的
```go println("C") // printC() println("--------------------------------") // printC() atomic.CompareAndSwapInt32(&c.sema1, 1, 0) // printC() println("B") // printB() atomic.CompareAndSwapInt32(&c.sema2, 1, 0) // printC() atomic.CompareAndSwapInt32(&c.sema2, 0, 1) // printB() println("C") // printC(), 下一次循环 println("--------------------------------") // printC() ``` |
7
Leprax 2021-03-05 13:25:03 +08:00
```go
type cond struct{ sema1 int32 sema2 int32 } func (c *cond)printA(){ for { if c.sema1==0{ println("A") atomic.CompareAndSwapInt32(&c.sema1,0,1) } } } func (c *cond)printB(){ for { if c.sema1==1&& c.sema2==0{ println("B") atomic.CompareAndSwapInt32(&c.sema2,0,1) } } } func (c *cond) printC(){ for { if c.sema2==1 { println("C") println("--------------------------------") atomic.CompareAndSwapInt32(&c.sema1, 1, 0) atomic.CompareAndSwapInt32(&c.sema2, 1, 0) } } } func main() { var con =new (cond) con.sema1=0 con.sema2=0 go con.printC() go con.printB() go con.printA() time.Sleep(5*time.Second) } ``` |
9
mauve 2021-03-05 15:30:27 +08:00
我运行了好多遍楼主的代码,结果都是
A B C -------------------------------- A B C -------------------------------- A B C -------------------------------- A B C -------------------------------- 这样输出,没有出现其他情况,楼主你说「但有时候 A 协程没有打印 A,结果变成了 BC 」 是什么样子的输出结果,可以解释一下吗 |
10
writesome6 2021-03-05 16:39:09 +08:00
用一个信号量就行了
``` const ( printA = iota printB printC ) type cond struct{ sema int32 } func (c *cond)printA(){ for { if c.sema == printA{ println("A") swapInt32 := atomic.CompareAndSwapInt32(&c.sema, 0, printB) if !swapInt32 { panic("A") } } } } func (c *cond)printB(){ for { if c.sema == printB{ println("B") if !atomic.CompareAndSwapInt32(&c.sema,printB,printC) { panic("B") } } } } func (c *cond) printC(){ for { if c.sema==printC { println("C") println("--------------------------------") if !atomic.CompareAndSwapInt32(&c.sema, printC, printA) { panic("C") } } } } func main() { var con =new (cond) go con.printC() go con.printB() go con.printA() time.Sleep(5*time.Second) } ``` |
11
Glauben 2021-03-05 16:52:10 +08:00
看的好难受啊
|
12
katsusan 2021-03-05 19:30:11 +08:00
@ldimple 按照楼上所说 printC 里即使两次不是原子操作,由于先执行的 CAS(sem1, 1, 0),此时 sema1=0, sema2=1,
应该也不会触发 printB 的条件(sema1=1,sema2=0)吧,为何会走进下面的 printB 逻辑里。 |