根据这里的定义,死锁与资源争用有关。
在操作系统中,当一个进程或线程进入等待状态时会发生死锁,因为请求的系统资源被另一个等待进程持有,而另一个等待进程又在等待另一个等待进程持有的另一个资源。如果一个进程不能无限期地改变它的状态,因为它请求的资源正在被另一个等待的进程使用,那么系统就被称为死锁。
在下面的代码中:
package main
import "fmt"
func main() {
c := make(chan string)
c <- "John"
fmt.Println("main() stopped")
}
Run Code Online (Sandbox Code Playgroud)
main() go-routine 阻塞,直到任何其他 go-routine(没有这样的)从该通道读取相同的数据。
但输出显示:
$ bin/cs61a
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/home/user/../myhub/cs61a/Main.go:8 +0x54
$
Run Code Online (Sandbox Code Playgroud)
编辑:
重点是:“主 goroutine 被阻塞,因此所有 goroutine 都被阻塞,因此这是一个死锁。” 在下面的代码中,非主协程也在通道上被阻塞,不是所有的协程都应该被阻塞吗?
package main
import (
"fmt"
"time"
)
func makeRandom(randoms chan int) {
var ch chan int
fmt.Printf("print 1\n")
<-ch
fmt.Printf("print 2\n")
}
func main() {
randoms := make(chan …Run Code Online (Sandbox Code Playgroud) 我有 2 个从单个通道读取的 go-routines。4 秒后,我取消上下文并终止选择循环。在终止循环之前,我在通道上调用 close,因为有 2 个 go-routines close 被调用两次并导致恐慌,因为其中一个 go-routines 已经关闭了通道。目前我正在使用恢复来从恐慌中恢复过来,有没有更好的方法来做到这一点?
package main
import (
"context"
"fmt"
"sync"
"time"
)
func numberGen(ctx context.Context, numChan chan int) {
num := 0
doneCh := ctx.Done()
defer func() {
if r := recover(); r != nil {
fmt.Println("recovered from ", r)
}
}()
for {
select {
case <-doneCh:
fmt.Println("done generating...")
close(numChan)
return
default:
num++
numChan <- num
}
}
}
func main() {
ctx, cancelFn := context.WithCancel(context.Background())
numChan := make(chan …Run Code Online (Sandbox Code Playgroud) 这是一个非常简单的应用程序:
package main
import "fmt"
func main() {
for i:= 0; i < 100000; i++ {
go func (){
fmt.Println("hello message.")
}()
}
fmt.Scanln()
fmt.Println("done")
}
Run Code Online (Sandbox Code Playgroud)
在Windows上运行应用程序后,并查看Windows任务管理器,我看到了以下状态:
有人可以说为什么?
我来自Java / Scala,最近开始使用Go。在Java / Scala中,线程池非常普遍,并且至少有四个不同的原因将使用它们。
由于Goroutine是如此轻便,因此不需要1,即使提供一个很好,我们也可以创建某种类型的工作程序池而无需过多地麻烦解决2。
但是,我觉得在Go中我们不能处理3和4。
是因为不需要它还是仅仅是缺少功能?
以下两个代码之间的基本区别是什么?不知何故,在第二个示例demo_process2()中从未被调用,但在第一个示例中工作正常。
go func() {
Must(demo_process1())
}()
demo_process2()
Run Code Online (Sandbox Code Playgroud)
go Must(demo_process1())
demo_process2()
Run Code Online (Sandbox Code Playgroud)
其中Must():
func Must(err error) {
if err != nil {
panic(err)
}
}
Run Code Online (Sandbox Code Playgroud) 下面的代码:
// Sample program to show how to use the WithDeadline function
// of the Context package.
package main
import (
"context"
"fmt"
"time"
)
type data struct {
UserID string
}
func main() {
// Set a duration.
// duration := 150 * time.Millisecond
duration := time.Now().Add(3 * time.Second)
// Create a context that is both manually cancellable and will signal
// a cancel at the specified duration.
ctx, cancel := context.WithDeadline(context.Background(), duration)
defer cancel()
// Create a channel …Run Code Online (Sandbox Code Playgroud) 在下面的代码中使用atomic.AddInt64:
func main() {
// Number of goroutines to use.
const grs = 2
// wg is used to manage concurrency.
var wg sync.WaitGroup
wg.Add(grs)
// Create two goroutines.
for g := 0; g < grs; g++ {
go func() {
for i := 0; i < 2; i++ {
atomic.AddInt64(&counter, 1)
}
wg.Done()
}()
}
// Wait for the goroutines to finish.
wg.Wait()
// Display the final value.
fmt.Println("Final Counter:", counter)
}
Run Code Online (Sandbox Code Playgroud)
或在下面的代码中使用atomic.LoadInt64:
func writer(i …Run Code Online (Sandbox Code Playgroud) 在某些情况下,我无法解释猩猩的行为。我尝试举一个简单的例子。这是我自己的文件“ main.go”:
package main
import (
"fmt"
)
func print1() {
fmt.Println("print 1")
}
func print2() {
fmt.Println("print 2")
}
func print3() {
fmt.Println("print 3")
}
func main() {
for i:=0; i<3; i++ {
go print1()
}
for i:=0; i<3; i++ {
go print2()
}
for i:=0; i<3; i++ {
go print3()
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这3个功能(每个循环中被调用3次)同时执行,结果打印数字的顺序是不可预测的。我不明白为什么该程序可以编译并执行而没有任何错误,但是它在控制台上什么都没打印!实际上,好像在for内部的函数调用未执行。如果删除这些go子句,则打印内容将显示在控制台上。我得出的结论是,并行线程无权在控制台上打印。如何查看具有实际“并发”行为的这些打印件?
go ×8
goroutine ×8
concurrency ×3
channel ×1
deadlock ×1
function ×1
memory-leaks ×1
string ×1
threadpool ×1