goroutine相比java 多线程NIO有何优势

Python011

goroutine相比java 多线程NIO有何优势,第1张

NIO(非阻塞IO)是一种IO编程模型,Golang中的IO底层实现方式和java NIO模型一致,通俗点说就是都采用了EPOLL。 你在使用golang读文件的时候,goroutine 会默默的挂起,只是你不知道,当读完毕了,goroutine 再次恢复,但你不用担心,goroutine 的挂起和恢复没有java线程那样可怕,你可以认为goroutine 的挂起和恢复就是保存和恢复几个变量的值,其实也是这样的。

剩下的就是goroutine 和 java线程的区别了,goroutine是用户态的线程切换,java采用的是系统线程切换,用汇编语言描述是一个(java)调用int 80软中断,一个没有。 意味着goroutine更轻量级,可以同时相应成千上万的线程切换,java你创造上千个线程就有些吃力了。

因为java线程不能创造过多的线程,如果同时处理上万上千的请求时候,就要考虑在几十个线程来处理上万上千的请求,这就出现了很多请求和线程不可能一一对应,所以通常做法是每个线程分别处理单个请求各个阶段。好比流水线,请求是要加工的商品,每个线程处理一道工序,这样做的好处是每人都做自己熟悉的,对于程序来说每个线程执行的代码永远都是自己很短的一块,这样根据局部优化原理,更具备CPU,内存亲和力,利于JIT。说这样多,就是说如果线程和请求不能一一对应,流水线式的并发编程很麻烦,阅读性也很差,通常是线程A里面一段逻辑代码,线程B又有另一处处理的逻辑代码。

由于goroutine 的轻便,你可以将请求和goroutine 一一对应起来,不用考虑将请求在线程之间换来换去,只关心你的业务逻辑,这就是goroutine 的好处。

总结:

golang的goroutine让你比java更容易编写并发程序,但性能不会有差别(目前来说,golang性能还不能和java比,看过代码就知道了,GC弱到爆),代码不会减少,该写的逻辑还得写。ps,其实golang的(sched)go程切换代码虽然原理和java的fork-join框架一样,但是fork-join比golang的sched代码牛逼不少,开始膜拜Doug Lea吧,golang还有很长的路要走。

阻塞socket和非阻塞socket的区别: 1、读操作 对于阻塞的socket,当socket的接收缓冲区中没有数据时,read调用会一直阻塞住,直到有数据到来才返回。当socket缓冲区中的数据量小于期望读取的数据量时,返回实际读取的字节数。

1.基本的问题必须是从缓存中移除,其目的在于,需要在高速缓存级别,而不是对象的水平同步。 一种方式是通过具有对整个高速缓存仅在查找持有全局锁,一旦该对象的锁已被获取将被丢弃。这把锁可以是一个读写锁,举办写作只有一个线程将要删除的对象。所以一个线程,希望使用一个缓存对象会做:pthread_rwlock_rdlock(&cache_lock)

exampleObj * obj = Lookup(key)

pthread_mutex_lock(&obj->mutex)

pthread_rwlock_unlock(&cache_lock)

/* Do some work on obj */

pthread_mutex_unlock(&obj->mutex)

并且一个线程要摧毁一个缓存对象会做:pthread_rwlock_wrlock(&cache_lock)

exampleObj * obj = Lookup(key)

pthread_mutex_lock(&obj->mutex)

Remove(key)

pthread_rwlock_unlock(&cache_lock)

/* Do some cleanup work on obj */

pthread_mutex_unlock(&obj->mutex)

pthread_mutex_destroy(&obj->mutex)

(这里的Remove()函数从缓存中删除的函数 CodeGo.net,以便后续Lookup()函数不能返回它)。

2. 这是未定义的行为(一)企图摧毁锁定mutex锁,或(b)引用销毁mutex以外调用pthread_mutex_init重新创建它(请参阅,破坏你的共享mutex体的线程将要参加的其他锁定它,无论是(1)破坏首先发生,其他线程调用未定义的行为试图锁定的(b)或(2)锁定另一个线程首先发生和销毁线程调用(一)未定义行为。 你需要改变你的设计,使在积极争夺一个mutex体是永远不会被破坏。对于你的榜样,你可以破坏共享mutexmain之后所有的线程都接合。对于您所描述的程序,你可能需要插入一个引用计数的对象。

3. 我想摆脱缓存中的对象。现在如何摧毁/freemutex是否正确? pthread_mutex_destroy说,我们应该pthread_mutex_destroy而mutex锁。比方说,一个线程决定摧毁它需要使其释放锁,并做了pthread_mutex_destroy摧毁锁定的对象。恰好在等待对象锁的其他线程是什么? 嗯,我希望我得到你的本意吧,我有确切的问题。反正我认识,后来我是愚蠢的:抱怨的未定义行为pthread_mutex_*函数后,pthread_mutex_destroy()约SEGFAULTS访问后的一个指针时,free()。 大多数C程序模拟环绕模式,每一个程序必须确保这类破坏后不访问。良好的C程序将防止被到处传播的指针设计,这样的破坏只发生在明确的地方,在没有其他变量包含一个指针了。这不是在垃圾收集的语言都关心的问题。 解决方法1:使用引用计数就像是做了分配。该refcounter通过atomicity函数访问。 (使用glib,它包含了伟大的,便携式的东西) 溶液1B:使用引用计数像它完成分配,sperate种工人是从那些没有在后来的弱引用的重要的,以便它们不妨碍对象的破坏。 解决方法2:不要破坏mutex。为什么要节约RAM的trouble呢?只是要像128K对象的全局静态数组。添加至极表示对象的状态。 破坏,而不是仅仅与设置状态变量,以及在访问一个对象在“关闭”状态的线程的打印错误。 解决方案3-硬盘的方式:不要做并发。结合该处理器的系统上的号码相匹配的线程池,使用非阻塞IO,消息对象和状态机的设计。队列的每个任务,并让仅添加到队列中的其他的队列。把队列中的'选择'或'的pollfd'包含的套接字/ filedescriptors集。洗牌大数据(状态机的3D,使用结构与atomicityrefcounter和写复制语义。 这在大多数情况下是最高效的,稳定的和可维护的解决方案。 如果你做了什么与表现,认为atomicity操作两次。它们可以比mutex更昂贵。

4. 我不能与CAF在此同意。我们已经做了某些类似(如参考ifData_createReference&放大器ifData_removeReference例程ifMIB.c)。其基本思路是保持一个全局锁来保护整个对象列表,guard在列表中个别条目的对象级锁。 当我们要在列表中创建一个新的条目,以WRITE锁定在名单上添加一个新条目,使条目persistent添加到所有的单体。并释放锁列表。 当我们来看看,上/从访问列表中的条目,把名单上的读锁和搜索条目.a旦我们找到入口,采取目标锁定在读模式下进行只读操作/写模式把对象锁定为修改对象条目。现在,松开列表锁。现在,一旦我们完成了目标进入释放对象锁并进行处理。 当对象进入,必须从列表中删除,以列表的写锁。搜索和查找列表中的对象项。取对象条目的写锁定,这将确保你是唯一的目标。现在,请从清单中的条目,因为没有人可以更多在列表中搜索它。并释放对象锁然后,松开列表锁。现在销毁对象和释放对象的资源。