Skip to content

loom talks devox be 2019

landon edited this page Apr 21, 2020 · 2 revisions

翻译笔记-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 结构化并发

    • 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
Clone this wiki locally