java 并发 csp_CSP与并发编程
原标题:CSP与并发编程
随着Go语言的逐渐走红,CSP(Communicating Sequential Process)并发模型也更多地被程序员所谈论。
计算机科学中,CSP是一种描述并发系统交互模式的形式化语言,其交互模式是通过channel进行消息传递。Go语言借鉴了CSP模型的理论,使用goroutine(一种运行在用户态的协程)和在goroutine之间收发消息的channel实现了高效并发。为什么Go语言要使用CSP模型来实现并发呢?
本文将做一些粗浅的探讨,最后用支持CSP并发模型的编程语言实现简短的并发程序,并与Java实现的并发程序做性能比较。
先来看看几种并发编程模型。
多线程
提起并发编程,最常见的就是多线程编程。线程是操作系统能够进行调度的最小单位,共享同一进程的数据和资源,有内核线程和用户线程之分,由操作系统或用户进程调度。多线程的程序可以利用多核CPU,并行地处理多个任务。随着并发量增大,线程数增加,多线程的并发模型面临一些问题。
内存占用
64位JVM线程默认栈空间是1M,启动1024个线程理论上消耗1G的栈空间。由于线程需要内存较多,为避免内存耗尽,应用程序不应该大量创建线程。
线程调度
操作系统对线程进行调度也需要成本。线程挂起前会保存线程上下文到栈空间,再切换到可执行线程。线程数很多时,线程上下文切换会导致CPU开销变大。
使用线程池技术可以对多线程并发进行优化,线程池实现线程复用,避免频繁创建新线程和线程切换,控制了线程数量,减少了内存的消耗。但是在竞争共享数据的时候,需要用加锁来保护共享数据,这样也降低了程序的并发效率。
异步回调
为了充分利用CPU,不让线程空等待,在线程阻塞的时候,注册一个回调方法,让当前线程不再阻塞,去处理新的请求。等结果准备好,调度器把结果传给回调方法,在回调方法中继续处理结果。然而回调方法并不在发起请求的线程里执行。
异步回调的缺点是所谓的callback hell。原本顺序同步的执行逻辑拆分到回调方法中,而且回调方法中可能再嵌套回调方法。这种写程序的方式还是让很多程序员不太习惯。异步回调的典型实现是NodeJS,目前也有一些第三方模块将异步代码同步化。
协程(纤程)
协程(纤程)也是一种异步方案。在代码IO阻塞时,当前协程让出CPU执行权,让其它协程执行。待IO操作完毕,阻塞的协程继续执行。虽然代码是异步执行,但写代码看起来像是同步的。协程是用户态的轻量级线程,现在的机器可以启动百万数量的协程。支持协程的编程语言实现了协程的调度器,提供了channel机制进行协程间通信(CSP模型中消息传递的实现)。基于CSP模型的协程方案,实现了无共享内存无锁的并发,可以匹配异步回调的性能。
CSP模型最初于Tony Hoare的1977年的论文中被描述,影响了许多编程语言的设计。
下面从被CSP模型所影响的编程语言中选择一个无名小卒,写一段简短的例子程序完成一个计算任务。
任务:计算0, 1, 2, ... 9999999的和。
硬件环境:4核i7-3520M 2.90GHz, MemTotal: 16121944 kB
N = 10* 1000* 1000
M = N / 4t1 = Time.nowchannel = Channel(Int32). new(M)#使用单线 程4协程
4.times { |i| spawn { M.times { |j| channel.send(i * M + j) } }}sum = 0_i64N.times { sum += channel.receive}t2 = Time.nowputs "telapsed time: #{t2 - t1}, sum=#{sum}"
运行结果:
Java1.8.0_121版本的例子程序
publicclassJava8Language{
privatestaticfinalintTIMES = 10* 1000* 1000;
publicstaticvoidmain(String[] args)throwsException{
finalCountDownLatch c = newCountDownLatch(TIMES);
finalAccumulator a = newAccumulator(c); longt1 = System.currentTimeMillis(); ExecutorService service = Executors.newFixedThreadPool( 4);
for( longi= 0;i
finalLong k = i; service.submit(() -> { a.add(k); c.countDown(); }); } c.await();
longt2 = System.currentTimeMillis(); System.out.printf( "telapsed time: %.3fs, sum=%dn", (t2-t1)/ 1000f,
a.getSum().longValue()); service.shutdown(); }}
classAccumulator{
privateAtomicLong sum = newAtomicLong( 0L);
privateCountDownLatch c;
publicAccumulator(CountDownLatch c){
this.c = c; }
AtomicLong getSum(){
returnsum; }
publicvoidadd(longk){ sum.addAndGet(k); }}
运行结果:
从结果来看,时间差距还是挺大的。
END
有兴趣的读者还可以用Go语言实现程序来比较。虽然Java在执行时间上落败,但这只是语言特性的原因。从解决实际的高并发问题来看,Java还有第三方库和框架可用。
责任编辑:
java 并发 csp_CSP与并发编程相关推荐
- java并发排它锁_Java并发编程进阶——锁(解析)
一.锁是什么 java开发中进行并发编程时针对操作同一块区域时,如果不加锁会出现并发问题,数据不是自己预计得到的值.我觉得有点像mysql事务中脏读.不可重复读.幻读的问题.加锁的目的是为了保证同一时 ...
- java并发常量_Java并发编程-常量对象(七)
在创建后状态不再发生改变的对象称作常量对象(Immutable Objects).常量对象其可靠性使其广泛地用作开发简单可靠代码的策略.常量对象在开发并发程序中非常有用.由于创建后不能被改变状态,它们 ...
- Java 从多线程到并发编程(五)—— 线程调度 优先级倒置(反转) 阻塞 死锁 suspend
文章目录 前言 ´・ᴗ・` 线程调度策略 优先级倒置问题 优先级倒置解决方案 死锁 dead lock suspend 被阻塞的同时持有资源不放 是上述问题的诱因 总结 ´◡` 前言 ´・ᴗ・` 这一 ...
- Java面试系列之并发编程专题-Java线程池灵魂拷问
金三银四跳槽季即将来临,想必有些猿友已经蠢蠢欲动在做相关的准备了!在接下来的日子里,笔者将坚持写作.分享Java工程师在面试求职期间的方方面面,包括简历制作.面试场景复现.面试题解答.谈薪技巧 以及 ...
- java 并发指南_并发编程 :Concurrent 用户指南 ( 下 )
原标题:并发编程 :Concurrent 用户指南 ( 下 ) 来源:高广超, www.jianshu.com/p/8cb5d816cb69 20. 锁 Lock java.util.concurre ...
- java实现分而治之_并发编程中一种经典的分而治之的思想!!
写在前面 在JDK中,提供了这样一种功能:它能够将复杂的逻辑拆分成一个个简单的逻辑来并行执行,待每个并行执行的逻辑执行完成后,再将各个结果进行汇总,得出最终的结果数据.有点像Hadoop中的MapRe ...
- java ee api_Java EE并发API教程
java ee api 这是一个示例章节,摘自Francesco Marchioni编辑的WildFly上的实用Java EE 7开发 . 本章讨论了新的Java EE并发API(JSR 236) , ...
- java jsr_分叉并加入Java 7 – JSR 166并发实用程序
java jsr Java 7最有趣的改进之一是对并发的更好支持. 借助JSR 166并发实用程序,我们获得了一些非常有用的并发改进. 在我看来,fork-join库在软件工程中具有很高的实际应用潜力 ...
- java并发调用_Java并发教程–可调用,将来
java并发调用 从Java的第一个发行版开始,Java的美丽之处之一就是我们可以轻松编写多线程程序并将异步处理引入我们的设计中. Thread类和Runnable接口与Java的内存管理模型结合在一 ...
最新文章
- header中Content-Disposition的作用与使用方法
- c4d流体插件_【C4D】流体插件详细讲解
- 我跑了ERNIE和BERT两个模型,结果出乎意料......
- Nginx教程-日志配置
- matlab边算边出图命令,Matlab:不包含边境和工具栏的figure(移除保存图片的白边)...
- 适用响应式 Web UI 框架
- 沈阳大学计算机考研,计算机专业考研成功经验谈:掌握方法,以不变应万变
- python工具包:Python Swiftclient
- 0成本副业项目,适合小白操作的信息差创业项目
- 洛谷P1330 封锁阳光大学(BFS, 并查集)
- (附源码)php二手服装网站 毕业设计201711
- 修改Windows 2003登录及关机界面(不出现关机提示、按CTRL+ALT+DEL开机)
- python猜随机数代码_猜随机数游戏Python
- Linux变量的定义、赋值、查看、删除(export、echo、unset)
- python 活体检测_基于Python+Keras+OpenCV实现实时人脸活体检测 | 文末送书
- 【妙python】按照元素长度排序列表
- 被裁员后,35岁程序员找了6份兼职,35岁被载的命运,谁能逃脱?
- 如何查询网站IP地址
- Hibernate查询性能优化技巧
- 解决麒麟系统arm环境无法安装pyinstaller的错误:Checking for library z : not found
热门文章
- 【代码审计-JAVA】基于javaweb框架开发的
- 计算机运维中常见英语单词,芯片常用英文词汇整理.doc
- edge浏览器如何把网页放到桌面_win10怎么把网页放在桌面上
- 【在线研讨会-倒计时】12月12日Softing工业物联网解决方案 助力工业4.0
- 虚拟机是什么?有什么用
- 没有躲过的坑--C++函数的默认参数(重新定义默认参数)
- android屏蔽表情输入法,Android中EditText屏蔽第三方输入法表情的方法示例
- java word创建表格_Java 在Word中创建表格
- project2016如何设置日历
- 计算机病毒与防治的教案,计算机病毒及防治教案