这里有一些背景知识:
我需要在go例程之间共享一个计数器变量,用于类似漏桶的东西.我知道在Effective Go,并发部分中有一个漏桶的例子,但是我需要跟踪的数量可能非常大,我觉得使用频道中的元素数来跟踪它是低效的.所以我正在考虑在不同的例程之间使用共享变量来跟踪数字.
据我所知,没有显式配置,所有go例程都映射到一个线程.但是,如果我在多核计算机上为程序分配多个线程,那么增量运算符是原子的吗?它是针对不同的数据类型(都是一样的int32,float32等等)在不同的机器(x86_32,x86_64,arm)?
更具体的说,如果我counter += 1000在一个例程中,counter -= 512在另一个例程中,并且这两个例程恰好在两个线程中运行,该怎么办?我需要担心线程安全吗?我要把枪锁上counter吗?
我想要做的是侦听 IPv6 的以太网帧并响应特定端口上的 UDP 调用。
我能够捕获我关心的以太网帧并解析出 UDP 有效负载,但是当我尝试回显该有效负载时,我遇到了问题。这是我的“服务器”代码:
func main() {
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(htons(syscall.ETH_P_IPV6)))
iface, err := net.InterfaceByName("lo")
if err != nil {
log.Fatal(err)
}
err = syscall.BindToDevice(fd, iface.Name)
if err != nil {
log.Fatal(err)
}
for {
buf := make([]byte, iface.MTU)
n, callerAddr, err := syscall.Recvfrom(fd, buf, 0)
if err != nil {
log.Fatal(err)
}
data := buf[:n]
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
udpPacket := packet.Layer(layers.LayerTypeUDP)
if udpPacket != nil {
udpPck, _ := udpPacket.(*layers.UDP)
// …Run Code Online (Sandbox Code Playgroud) Go的缓冲通道本质上是一个线程安全的FIFO队列.(请参阅是否可以将Go的缓冲通道用作线程安全队列?)
我想知道它是如何实现的.它是无锁的,如有多个读或写线程的无锁队列吗??
Go的src目录(grep -r Lock .|grep chan)中的greping 给出了以下输出:
./pkg/runtime/chan.c: Lock;
./pkg/runtime/chan_test.go: m.Lock()
./pkg/runtime/chan_test.go: m.Lock() // wait
./pkg/sync/cond.go: L Locker // held while observing or changing the condition
Run Code Online (Sandbox Code Playgroud)
但是不要锁定我的机器(MacOS,intel x86_64).有没有官方资源来验证这个?