我的应用程序有多个线程将消息发布到单个 RabbitMQ 集群。
阅读兔子文档:我阅读了以下内容:
对于使用多个线程/进程进行处理的应用程序,为每个线程/进程打开一个新通道而不是在它们之间共享通道是很常见的。
我明白,与其打开多个连接(昂贵),
不如打开多个通道。
但为什么不对所有线程使用单个通道呢?
与单个渠道相比,使用多个渠道有哪些好处?
我一直在寻找与结合原生 android 和 dart 相关的教程,到目前为止这是最好的https://proandroiddev.com/communication- Between-flutter-and-native-modules-9b52c6a72dd2 但它是用 kotlin 写的,我也尝试在java上编写代码,但是当我尝试调用XML文件并且使用“R”的小部件出现错误时,它说“无法解析符号”,很多人说R问题可以通过干净的项目或解决重建,但我在 android studio 中使用 flutter,其同步、清理或重建功能不可用。如果你们知道解决方案,我很高兴如果你们愿意提供帮助
我听说这比你的程序高并发的时候channel要好。sycn.Mutex.Lock()但为什么渠道效率更高呢?在我看来,要实现一个安全的缓冲池(我认为channel可以被认为是一个缓冲池),你必须使用锁。
如果channel效率更高,为什么会有sycn.Mutex?因为我可以编写下面的代码来模拟sync.Mutex。
type seme struct {
lock chan int
locked bool
}
func (l *seme)Lock() {
// state 0 for initial, 1 for locked, 2 for free.
if atomic.CompareAndSwapInt32(&l.state, 0, 1) {
l.lock = make(chan int, 1)
}
l.lock <- 0
l.state = 1
}
func (l *seme)UnLock() {
if !atomic.CompareAndSwapInt32(&l.state, 1, 2) {
panic("UnLock a free Lock")
}
l.state = 2
<- l.lock
}
Run Code Online (Sandbox Code Playgroud)
如果channel到处都比mutex,我为什么要使用 …
我的解决方案如下,但是以下代码中是否存在竞争条件(它会出现恐慌)吗?
c := make(chan struct{})
for i := 0; i < 1000000; i++ {
go func() {
select {
case <-c:
default:
close(c)
}
}()
}
Run Code Online (Sandbox Code Playgroud)
我认为是的,但是 go test -race 没有检测到它,并且根据经验,我无法让它恐慌。
我现在正在读《Go中的并发》这本书,这个决策树是为了教我们选择“原语”或“通道”而设计的。
\n\n\n它是性能关键部分吗?
\n
\n\n这绝对并不意味着,\xe2\x80\x9c我希望我的程序具有高性能,因此我只会使用互斥体。\xe2\x80\x9d 相反,如果您已经分析了程序的一部分,并且它变成了发现这是一个主要瓶颈,比程序的其余部分慢几个数量级,使用内存访问同步原语可能有助于该关键部分在负载下执行。这是因为通道使用内存访问同步来操作,因此它们只能更慢。然而,在我们考虑这一点之前,性能关键部分可能会暗示我们需要重组我们的程序。
\n
但它仍然不能解释为什么我们应该使用channels,因为performance总是很重要\xe2\x80\x9c我希望我的程序具有高性能,因此我只会使用互斥体。\xe2\x80\x9d
所以我仍然不知道如何选择使用互斥体或通道。
\n我有一个SSE端点将数据发送到前端,并且该数据是从另一个API端点检索的。channels我对in还很陌生go,似乎我必须触发 API 端点两次,以便 SSE 端点将数据发送到前端一次。就目前而言,我还没有编写前端代码来建立 SSE 连接,因为我仍在使用通道。有人可以解释为什么这需要调用 API 两次才能让 SSE 发送数据吗?
上交所路线
func SendSSE(appCtx *fiber.Ctx, dataChannel chan string) error {
appCtx.Set("Content-Type", "text/event-stream")
appCtx.Set("Cache-Control", "no-cache")
appCtx.Set("Connection", "keep-alive")
appCtx.Set("Transfer-Encoding", "chunked")
appCtx.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
log.Println("SSE Opened")
for {
log.Println("Retrieving data channel..")
fmt.Fprintf(w, "data: Message: %s\n\n", <-dataChannel)
log.Println(<-dataChannel)
err := w.Flush()
if err != nil {
// Refreshing page in web browser will establish a new
// SSE connection, but only (the last) one is alive, …Run Code Online (Sandbox Code Playgroud) 根据我的理解:当通道满时,GO中的缓冲通道不是FIFO.
我在我的应用程序中需要这种行为(FIFO行为).
我怎样才能实现这种行为?那有什么开源吗?
提前致谢
编辑:
有些人不喜欢这个问题,所以让我更清楚一点:
我的意思是当缓冲频道已满并且多个发送者
在尝试向频道添加项目时被阻止时,他们将被释放的顺序
不是FIFO.您还可以阅读以下讨论:https://github.com/golang/go/issues/11506
所以,是的,我正在寻找实现这种行为的第三方库.
对不起,不清楚.
我有一个缓冲的通道,可以通过多个(在此示例中为4)go例程读取。
queue := make(chan string, 10000) // a large buffered channel
Run Code Online (Sandbox Code Playgroud)
每个go例程都会检查通道中可用的元素数量,并对所有元素进行处理。
for i :=0; i< 4; i++{ // spun 4 go routines
go func() {
for {
for elem := range queue {
// do something with the elem from the channel
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
多个go例程会在读取时发生冲突吗?换句话说,不同的go例程可以在通道中捕获相同的元素,还是一个go例程正在读取缓冲区,而另一个go例程已经读取并处理了某些元素?如何在阅读一个go例程的同时阻止其他go例程读取?
在编程中创建频道的最佳做法是什么?为了组织和清晰,您应该在主程序中创建所有通道吗?
我已经查看了在子例程中创建通道的代码.在子例程中创建主程序时,这些通道是否禁止进入主程序?
请澄清.提前致谢.
我有以下代码:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
ch2 := make(chan int)
go func(c chan int, c2 chan int) {
for {
select {
case v := <-c:
fmt.Println(v)
case v := <-c2:
fmt.Println(v)
default:
}
}
}(ch, ch2)
ch <- 1
close(ch)
close(ch2)
time.Sleep(10 * time.Second)
}
Run Code Online (Sandbox Code Playgroud)
当我运行此命令时,它会打印1到标准输出,然后继续打印0。为什么是这样?
我知道我可以在goroutine中检查通道是否关闭,但是我只是想知道原因。
另外,假设我要在关闭所有(多个)通道后从goroutine退出,这可能吗?我以为一旦关闭了所有通道,在所有通道都关闭后,在默认情况下我有可能退出goroutine