189 8069 5689

go语言中的锁太多了 go 锁机制

go语言到底有什么好处

1. 部署简单

10年积累的成都做网站、成都网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站制作后付款的网站建设流程,更有金坛免费网站建设让你可以放心的选择与我们合作。

Go

编译生成的是一个静态可执行文件,除了glibc外没有其他外部依赖。这让部署变得异常方便:目标机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。

2. 并发性好

Goroutine和channel使得编写高并发的服务端软件变得相当容易,很多情况下完全不需要考虑锁机制以及由此带来的各种问题。单个Go应用也能有效的利用多个CPU核,并行执行的性能好。

3. 良好的语言设计

从学术的角度讲Go语言其实非常平庸,不支持许多高级的语言特性;但从工程的角度讲,Go的设计是非常优秀的:规范足够简单灵活,有其他语言基础的程序员都能迅速上手。更重要的是

Go 自带完善的工具链,大大提高了团队协作的一致性。

4. 执行性能好

虽然不如 C 和 Java,但相比于其他编程语言,其执行性能还是很好的,适合编写一些瓶颈业务,内存占用也非常省。

Go 语言 channel 的阻塞问题

Hello,大家好,又见面了!上一遍我们将 channel 相关基础以及使用场景。这一篇,还需要再次进阶理解channel 阻塞问题。以下创建一个chan类型为int,cap 为3。

channel 内部其实是一个环形buf数据结构 ,是一种滑动窗口机制,当make完后,就分配在 Heap 上。

上面,向 chan 发送一条“hello”数据:

如果 G1 发送数据超过指定cap时,会出现什么情况?

看下面实例:

以上会出现什么,chan 缓冲区允许大小为1,如果再往chan仍数据,满了就会被阻塞,那么是如何实现阻塞的呢?当 chan 满时,会进入 gopark,此时 G1 进入一个 waiting 状态,然后会创建一个 sudog 对象,其实就sendq队列,把 200放进去。等 buf 不满的时候,再唤醒放入buf里面。

通过如下源码,你会更加清晰:

上面,从 chan 获取数据:

Go 语言核心思想:“Do not communicate by sharing memory; instead, share memory by communicating.” 你可以看看这本书名叫:Effective Go

如果接收者,接收一个空对象,也会发生什么情况?

代码示例 :

也会报错如下:

上面,从 chan 取出数据,可是没有数据了。此时,它会把 接收者 G2 阻塞掉,也是和G1发送者一样,也会执行 gopark 将状态改为 waiting,不一样的点就是。

正常情况下,接收者G2作为取出数据是去 buf 读取数据的,但现在,buf 为空了,此时,接收者G2会将sudog导出来,因为现在G2已经被阻塞了嘛,会把G2给G,然后将 t := -ch 中变量 t 是在栈上的地址,放进去 elem ,也就是说,只存它的地址指针在sudog里面。

最后, ch - 200 当G1往 chan 添加200这个数据,正常情况是将数据添加到buf里面,然后唤醒 G2 是吧,而现在是将 G1 的添加200数据直接干到刚才G2阻塞的t这里变量里面。

你会认为,这样真的可以吗?想一想,G2 本来就是已经阻塞了,然后我们直接这么干肯定没有什么毛病,而且效率提高了,不需要再次放入buf再取出,这个过程也是需要时间。不然,不得往chan添加数据需要加锁、拷贝、解锁一序列操作,那肯定就慢了,我想Go语言是为了高效及内存使用率的考虑这样设计的。(注意,一般都是在runtime里面完成,不然会出现象安全问题。)

总结 :

chan 类型的特点:chan 如果为空,receiver 接收数据的时候就会阻塞等待,直到 chan 被关闭或者有新的数据到来。有这种个机制,就可以实现 wait/notify 的设计模式。

相关面试题:

go语言的map多协程访问时需要加锁吗

go语言的map多协程访问时需要加锁

支持==和!=操作就可以做key,实际上只有function、map、slice三个kind不支持作为key,因为只能和nil比较不能和另一个值比较。布尔、整型、浮点、复数、字符串、指针、channel等都可以做key。

struct能不能做key要看每一个字段,如果所有字段都可以做key,那这个struct就可以。有一个字段不能做key,这个struct就不能做key。array也是,元素类型能做key,那这个array就可以。

例如:

type Foo map[struct {

B bool

I int

F float64

C complex128

S string

P *Foo

Ch chan Foo

}]bool

每一个字段都可以做key,Foo就可以做key。再如:

type Foo map[struct {

Fn func() Foo

M map[*Foo]int

S []Foo

}]bool

有一个字段不能做key、Foo就不允许做key,而这三个字段都不能。

字段是递归检查的:

type Foo map[struct {

Sub struct {

M map[*Foo]bool

}

}]bool

Sub的M字段不能做key,Sub就不能做key,Foo也就不能做key。

总之想把一个数据结构用于map的key,就不能包含function、map和slice。


当前文章:go语言中的锁太多了 go 锁机制
当前URL:http://cdxtjz.com/article/hggcog.html

其他资讯