我有一个代码,比如,
Routine 1 {
runtime.LockOSThread()
print something
send int to routine 2
runtime.UnlockOSThread
}
Routine 2 {
runtime.LockOSThread()
print something
send int to routine 1
runtime.UnlockOSThread
}
main {
go Routine1
go Routine2
}我使用运行时lock-unlock,因为我不希望例程1的打印与例程2的打印混合。但是,在执行上述代码后,它的输出与没有lock-unlock的输出相同(意味着打印输出混合)。有没有人能告诉我为什么会发生这种事情,以及如何迫使它发生。
注:我举了一个打印东西的例子,但是有很多打印和发送事件。
发布于 2011-12-05 05:12:08
如果你想序列化"print something",例如每个"print something“都应该自动执行,那么只需序列化它即可。
你可以用一个互斥锁来包围“打印一些东西”。这将工作,除非代码死锁,因为它肯定可以很容易地在一个非平凡的程序中。
Go序列化某些东西的最简单方法是使用通道。将应该打印的所有东西收集到一个(Go)例程中。当打印单元的收集完成时,通过通道将其发送到某个打印“代理”作为“打印作业”单元。该代理将简单地接收其“任务”,并自动打印每个任务。人们可以免费获得这种原子性,并且作为一个重要的额外好处,在只有不相互依赖的“打印单元”生成goroutines的简单情况下,代码不会再容易地死锁。
我的意思是这样的:
func printer(tasks chan string) {
for s := range tasks {
fmt.Printf(s)
}
}
func someAgentX(tasks chan string) {
var printUnit string
//...
tasks <- printUnit
//...
}
func main() {
//...
tasks := make(chan string, size)
go printer(tasks)
go someAgent1(tasks)
//...
go someAgentN(tasks)
//...
<- allDone
close(tasks)
}发布于 2011-12-05 04:58:46
runtime.LockOSThread所做的是防止任何其他goroutine在同一线程上运行。它强制运行时创建一个新线程并在那里运行Routine2。它们仍在并发运行,但运行在不同的线程上。
相反,您需要使用sync.Mutex或某些通道魔术。
您很少需要使用runtime.LockOSThread,但它对于强制一些更高优先级的goroutine在它自己的线程上运行很有用。
package main
import (
"fmt"
"sync"
"time"
)
var m sync.Mutex
func printing(s string) {
m.Lock() // Other goroutines will stop here if until m is unlocked
fmt.Println(s)
m.Unlock() // Now another goroutine at "m.Lock()" can continue running
}
func main() {
for i := 0; i < 10; i++ {
go printing(fmt.Sprintf("Goroutine #%d", i))
}
<-time.After(3e9)
}发布于 2011-12-05 03:52:15
我认为,这是因为runtime.LockOSThread(),runtime.UnlockOSThread并不是一直都能工作。它完全取决于CPU,执行环境等。它不能通过任何其他方式强制执行。
https://stackoverflow.com/questions/8378092
复制相似问题