-
Notifications
You must be signed in to change notification settings - Fork 45
loom talks devox be 2019
Devoxx BE 2019- Project Loom: Helping Write Concurrent Applications on the Java Platform by Ron Pressler
-
talks说明
- 异步编程技术正日益普及,从简单的callback到所谓的reactive api,再到特定语言构造的async/await。
- 基于阻塞io操作,在传统的编程技术中无法扩展,是因为os内核线程作为并发单元太重,无法表示业务的细粒度单元。上述技术付出了很大的代价,但是无法与命令式编程语言的核心思想完美集成。
- Loom决定在运行时而提供轻量级的线程实现,继续保留命令式编程代码这种最自然的抽象:线程和同步操作
-
talks笔记
-
Rethinking Concurrent Applications on the Java Platform
-
Synchronous 同步
- 代码可读性好、非常适合编程语言中(控制流,异常)、非常适合工具(调试器,分析)
- 创建和阻塞的成本很高、资源有限
- 对程序员友好,对操作系统/硬件不友好
-
Asynchronous 异步
- 扩展性好
- 代码可读性不好、很难调试和分析、侵入性强,几乎不可能移植
- 对程序员不好友,对操作系统/硬件友好
-
同步 vs 异步
- 同步:简单、扩展性较差、对程序员友好
- 异步:扩展性较好、复杂、不可互操作的(非命令式编程)、很难调试和分析、对程序员不好友
-
Java中的线程
- java.lang.Thread
- 到目前为止,是用OS线程作为实现
- os线程必须支持所有语言的所有应用程序
- 任务切换需要切换到内核
- 内存占用大-兆规模;页面粒度大;不能取消提交
- 所有的用法调度都是折中方案。不好的本地cache
-
Rethink threads
-
轻量级/虚拟的线程以被调度器管理的重量级/内核线程为载体
-
Codes Like Sync,Works Like Async
- 写代码像同步,但是工作像异步
- 对程序员和操作系统/硬件都友好
-
内存占用小,切换快
-
向前兼容:所以已经存在的代码都能拥有这个新特性
-
我们想纠正过去的错误,重新开始
-
Thread.currentThread()和ThreadLocal的使用无处不在,需要做支持否则现有的代码很少可以运行
-
从Java5开始,我们鼓励人们不再直接使用Thread API。人们使用Executor和Future的话,那么过去的api错误和历史包袱则不是很明显
-
Thread需要通过移除长期废弃的方法来清理
-
我们可以大大减少Thread的占用空间
-
rethink
- java.lang.Thread
- Java运行时可以很好的实现线程
- 任务切换在用户态,虚拟机支持(continuations)
- 可插拔的调取器,默认为事务优化
- 可调整大小的堆栈
- 不支持native代码的阻塞
-
-
Structured Concurrency 结构化并发
-
Trio: a friendly Python library for async concurrency and I/O
-
结构化
- 运行时行为反应了代码的结构,按块组织
- 代码的结构展示了流程控制的开始和结束
-
结构化并发
- Excucutor、Future都是非结构化的
try(var scope = ThreadScope.open()) { scope.start(task1); scope.start(task2) }
-
结构化并发:取消
try(var scope = ThreadScope.open(PROPAGATE_CANCEL)) { scope.start(task1); scope.start(task2) }
-
结构化并发:截止日期
try(var scope = ThreadScope.open(Instant.now().plusSeconds(30))) { scope.start(task1); scope.start(task2) }
-
Thread Locals
- ThreadLocal变量,上下文ClassLoader、InheritableThreadLocal、AccessControlContext
- 和线程池配合不好
- 易变且非结构化
- 动态的,不是那么快
-
Scope Locals
static final Scoped<Integer> s1 = Scoped.forType(Integer.class); static final Scoped<String> s2 = Scoped.forType(String.class); try(s1.bind(1);s2.bind("hello")) { System.out.println(foo());// prints hello1 } String foo() { return s1.get() + s2.get(); } try(s1.bind(1);s2.bind("hello")) { System.out.println(foo()); // prints hello1 try(s1.bind(2);s2.bind("goodbye")) { System.out.println(foo()); // prints goodbye2 } System.out.println(foo()); // prints hello1 } try(s1.bind(99);s2.bind("hello")) { try(var scope = ThreadScope.open()) { scope.start(task1); scope.start(task2) } }
- scope locals有望取代threadlocal的绝大多数用法
- 也在探索processor locals
- 可命名线程继承thread locals
-
Continuations
class Continuation implements Runnable { public Continuation(ContinuationScope scope,Runnable body); public void run(); public boolean isDone(); public static void yield(ContinuationScope scope); } Continuation cont = new Continuation(SCOPE,() -> { System.out.println("before"); Continuation.yield(SCOPE); System.out.println("after"); }); cont.run(); // prints before cont.isDone(); // false cont.run();// prints after cont.isDone();// true
-
thread = yield control and resume + execution scheduling
-
thread = continuation + scheduler
package java.util.concurrent.locks; public class LockSupport { public static void park(...) { var t = Thread.currentThread(); if(t.isLightweight()) { Continuations.yield(FIBER_SCOPE); } else { Unsafe.park(false,0L); } } public static void unpark(Thread thread) { if(thread.isLightweight()) { t.scheduler.submit(t.continuation); } else { Unsafe.unpark(thread); } } }
-
var readLock = new ReentrantLock(); readLock.lock();
- ForkJoinPool -> Fiber.runContinuation() -> Continuation.run() -> Continuation.enter -> ReentrantLock.lock() -> Fiber.park() -> Continuation.yield
-
var listener = new ServerSocket(...); listener.accept();
- ForkJoinPool -> Fiber.runContinuation() -> Continuation.run() -> Continuation.enter -> ServerSocket.accept -> Fiber.park() -> Continuation.yield
-
Continuations的限制
- 运行native代码的continuation栈无法暂停
- 当持有一个monitor时无法暂停(临时)
-
项目的状态
- java.util.concurrent可以工作,但是需要重新调整
- Thread.sleep
- java.net.Socket/ServerSocket(JDK 13)
- java.nio.channels.SocketChannel and friends(JDK 11)
- JSSE implementation of TLS
- AccessController.doPrivileged w/o native frame(JDK 12)
- java.lang.reflect.Method.invoke需要更多工作
- Monitors/Object.wait() 临时用Thread实现
- Native frames - thread实现
- debugger support- 调试支持
-
进一步的工作
- java.net.InetAddress
- Console I/O
- File I/O ?
- Channels ?
- JFR
- Performance
-