并发实现的异和同(Java,go)

Java中多线程之间是通过共享内存进行通信的,在go中多线程之间通信是基于消息的,go的channel是go中多线程通信的基石。

对于Java来说,共享的资源主要靠锁实现。synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
映射到JVM层次:
synchronized 同步语句块,使用的是 monitorenter 和 monitorexit 指令。当执行 monitorenter 指令时,线程试图获取锁也就是获取 monitor(monitor对象存在于每个Java对象的对象头中,synchronized 锁便是通过这种方式获取锁的,也是为什么Java中任意对象可以作为锁的原因) 的持有权.当计数器为0则可以成功获取,获取后将锁计数器设 为1也就是加1。相应的在执行 monitorexit 指令后,将锁计数器设为0,表明锁被释放。
synchronized 修饰方法,底层使用ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法,JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

对于go而言,主要依靠channel实现多线程通信。下图就展示两个 goroutine 利用无缓冲channel共享一个资源。
在这里插入图片描述
在第 1 步,两个 goroutine 都到达通道,但哪个都没有开始执行发送或者接收。
在第 2 步,左侧的 goroutine 将它的手伸进了通道,这模拟了向通道发送数据的行为。这时,这个 goroutine 会在通道中被锁住,直到交换完成。
在第 3 步,右侧的 goroutine 将它的手放入通道,这模拟了从通道里接收数据。这个 goroutine 一样也会在通道中被锁住,直到交换完成。
在第 4 步和第 5 步,进行交换。
在第 6 步,两个 goroutine 都将它们的手从通道里拿出来,这模拟了被锁住的 goroutine 得到释放。两个 goroutine 现在都可以去做别的事情了。

几个主要差异:
创建了一线程并启动,在java中main也是用户线程,main结束不代表所有用户线程结束,但main不结束,jvm一定不会退出,当不存在用户线程时,jvm进程就退出了(不管main函数所在线程是否已经结束);在Golang中,通过go关键字开启一个协程,执行匿名函数里面的内容,这里需要注意main函数所在线程需要休眠以下,以便等开启的协程执行,这是因为go中只要main函数线程退出则进程就退出

在java中创建的线程与os线程一一对应,所以java中的每个线程占用一个时间片来运行;而go中多个协程对应一个os 线程,也就是多个协程对应了一个时间片,go则使用自己的调度策略(非os的调度策略)来让多个协程使用一个时间片来并发的运行(这也是go的并发编程优势)。

对于锁而言,java中的锁是synchronized或者ReentrantLock,java中synchronized关键字对不同对象使用有不同的效果;对于go来说锁只有一个:sync.Mutex,ync.Mutex是不可重入的锁,多次对sync.Mutex加锁会导致死锁。

并发同步编程,Java主要依靠wait/notify等方法来实现;而go则是使用chanel来进行协程之间的通信实现。(可以通过两个语言的生产者和消费者设计模式的实现去体会。)

我是pavel,一位憨憨傻傻的程序员,平时幽默又有才,专注于Java开发。不定时发送些腾讯程序员的工作/生活日常,请大家多多关注我的公众号!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值