标签: goroutine

为什么通道上的 go-routine 块被认为是死锁?

根据这里的定义,死锁与资源争用有关。

在操作系统中,当一个进程或线程进入等待状态时会发生死锁,因为请求的系统资源被另一个等待进程持有,而另一个等待进程又在等待另一个等待进程持有的另一个资源。如果一个进程不能无限期地改变它的状态,因为它请求的资源正在被另一个等待的进程使用,那么系统就被称为死锁。


在下面的代码中:

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)

deadlock go goroutine

-2
推荐指数
1
解决办法
224
查看次数

如何处理关闭同一个通道的多个 go-routines?

我有 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)

go goroutine

-2
推荐指数
1
解决办法
229
查看次数

为什么简单的Go应用会消耗大量内存

这是一个非常简单的应用程序:

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任务管理器,我看到了以下状态:

进入应用状态

有人可以说为什么?

string memory-leaks go goroutine

-3
推荐指数
1
解决办法
113
查看次数

Go提供与Threadpool等效的功能吗

我来自Java / Scala,最近开始使用Go。在Java / Scala中,线程池非常普遍,并且至少有四个不同的原因将使用它们。

  1. 重用工人已经实例化
  2. 资源管理。当我们有多个线程池时,我们可以确保如果系统的某个部分中发生了突发,那么它不会阻止其他部分的运行。
  3. 自定义我们想要的计划类型(分叉/联接,经典,计划等)
  4. 自定义拒绝策略。

由于Goroutine是如此轻便,因此不需要1,即使提供一个很好,我们也可以创建某种类型的工作程序池而无需过多地麻烦解决2

但是,我觉得在Go中我们不能处理34

是因为不需要它还是仅仅是缺少功能?

concurrency go threadpool goroutine

-3
推荐指数
1
解决办法
88
查看次数

Goroutine 概念:直接调用 vs 使用函数字面量调用

以下两个代码之间的基本区别是什么?不知何故,在第二个示例demo_process2()中从未被调用,但在第一个示例中工作正常。

    1.
go func() {
    Must(demo_process1())
}()

demo_process2()
Run Code Online (Sandbox Code Playgroud)
    2.
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)

concurrency go goroutine

-3
推荐指数
1
解决办法
119
查看次数

上下文 - WithDeadline() 与 WithTimeout()

下面的代码:

// 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)

channel go goroutine

-4
推荐指数
2
解决办法
1356
查看次数

atomic.AddInt64() 是否强制从/向主内存获取/更新值?

在下面的代码中使用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)

go goroutine

-4
推荐指数
1
解决办法
44
查看次数

为什么这些goroutine无法打印到控制台?

在某些情况下,我无法解释猩猩的行为。我尝试举一个简单的例子。这是我自己的文件“ 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子句,则打印内容将显示在控制台上。我得出的结论是,并行线程无权在控制台上打印。如何查看具有实际“并发”行为的这些打印件?

concurrency function go goroutine

-5
推荐指数
1
解决办法
76
查看次数