版 本 : 2010-07-29 Java 并 发 程 序 设 计 教 程 温 绍 锦 ( 昵 称 : 温 少 ) 邮 箱 :szujobs@hotmail.com 旺 旺 :shaojinwensj QQ: 1420452 Blog:http://www.cnblogs.com/jobs/ 旧 时 王 谢 堂 前 燕, 飞 入 寻 常 百 姓 家
内 容 列 表 1 使 用 线 程 的 经 验 : 设 置 名 称 响 应 中 断 使 用 ThreadLocal 2 Executor :ExecutorService 和 Future 3 阻 塞 队 列 : put 和 take offer 和 poll drainto 4 线 程 间 的 协 调 手 段 :lock condition wait notify notifyall 5 Lock-free: atomic concurrentmap.putifabsent CopyOnWriteArrayList 6 关 于 锁 使 用 的 经 验 介 绍 7 并 发 流 程 控 制 手 段 :CountDownlatch Barrier 8 定 时 器 : ScheduledExecutorService 大 规 模 定 时 器 TimerWheel 9 并 发 三 大 定 律 :Amdahl Gustafson Sun-Ni 10 神 人 和 图 书 11 业 界 发 展 情 况 : GPGPU OpenCL 12 复 习 题 学 习 的 过 程, 着 重 注 意 红 星 标 识 的 内 容, 学 完 之 后, 要 求 能 够 回 答 复 习 题
启 动 线 程 的 注 意 事 项 Thread thread = new Thread("thread name") { public void run() { // do xxx ; thread.start(); public class MyThread extends Thread { public MyThread() { super("thread name"); public void run() { // do xxx MyThread thread = new MyThread (); thread.start(); Thread thread = new Thread() { public void run() { // do xxx ; thread.setname("thread name"); thread.start(); 1 3 2 Thread thread = new Thread(task); // 传 入 任 务 thread.setname( thread name"); thread.start(); 4 Thread thread = new Thread(task, thread name"); thread.start(); 5 无 论 何 种 方 式, 启 动 一 个 线 程, 就 要 给 它 一 个 名 字! 这 对 排 错 诊 断 系 统 监 控 有 帮 助 否 则 诊 断 问 题 时, 无 法 直 观 知 道 某 个 线 程 的 用 途
要 响 应 线 程 中 断 thread.interrupt(); Thread thread = new Thread("interrupt test") { public void run() { for (;;) { doxxx(); if (Thread.interrupted()) { break; ; thread.start(); public void foo() throws InterruptedException { if (Thread.interrupted()) { throw new InterruptedException(); 1 2 Thread thread = new Thread("interrupt test") { public void run() { for (;;) { try { doxxx(); catch (InterruptedException e) { break; catch (Exception e) { // handle Exception ; thread.start(); 3 程 序 应 该 对 线 程 中 断 作 出 恰 当 的 响 应
ThreadLocal ThreadLocal<T> initialvalue() : T get() : T set(t value) remove() 顾 名 思 义 它 是 local variable( 线 程 局 部 变 量 ) 它 的 功 用 非 常 简 单, 就 是 为 每 一 个 使 用 该 变 量 的 线 程 都 提 供 一 个 变 量 值 的 副 本, 是 每 一 个 线 程 都 可 以 独 立 地 改 变 自 己 的 副 本, 而 不 会 和 其 它 线 程 的 副 本 冲 突 从 线 程 的 角 度 看, 就 好 像 每 一 个 线 程 都 完 全 拥 有 该 变 量 使 用 场 景 To keep state with a thread (user-id, transaction-id, logging-id) To cache objects which you need frequently 隐 式 传 参 注 意 : 使 用 ThreadLocal, 一 般 都 是 声 明 在 静 态 变 量 中, 如 果 不 断 的 创 建 ThreadLocal 而 且 没 有 调 用 其 remove 方 法, 将 会 导 致 内 存 泄 露
任 务 的 提 交 者 和 执 行 者 为 了 方 便 并 发 执 行 任 务, 出 现 了 一 种 专 门 用 来 执 行 任 务 的 实 现, 也 就 是 Executor 由 此, 任 务 提 交 者 不 需 要 再 创 建 管 理 线 程, 使 用 更 方 便, 也 减 少 了 开 销 ExecutorService Task Submitter Executor Thread Task Submitter Task Task Task Task Task Executor Thread Task Submitter Executor Thread java.util.concurrent.executors 是 Executor 的 工 厂 类, 通 过 Executors 可 以 创 建 你 所 需 要 的 Executor
任 务 的 提 交 者 和 执 行 者 之 间 的 通 讯 手 段 ExecutorService executor = Executors.newSingleThreadExecutor(); Callable<Object> task = new Callable<Object>() { public Object call() throws Exception { Object result = "..."; return result; ; Future<Object> future = executor.submit(task); future.get(); Future<T> cancel(boolean) : boolean iscancelled() : boolean isdone() : boolean get() : T 有 两 种 任 务 : get(long, TimeUnit) : T Runnable Callable Callable 是 需 要 返 回 值 的 任 务 Task Submitter Task Executor Future<Object> future = executor.submit(task); // 等 待 到 任 务 被 执 行 完 毕 返 回 结 果 // 如 果 任 务 执 行 出 错, 这 里 会 抛 ExecutionException future.get(); // 等 待 3 秒, 超 时 后 会 抛 TimeoutException future.get(3, TimeUnit.SECONDS); Callable<Object> task = new Callable<Object>() { public Object call() throws Exception { Object result = ; return result; ; Task Submitter 把 任 务 提 交 给 Executor 执 行, 他 们 之 间 需 要 一 种 通 讯 手 段, 这 种 手 段 的 具 体 实 现, 通 常 叫 做 Future Future 通 常 包 括 get( 阻 塞 至 任 务 完 成 ), cancel,get(timeout)( 等 待 一 段 时 间 ) 等 等 Future 也 用 于 异 步 变 同 步 的 场 景
阻 塞 队 列 producer consumer // 如 果 队 列 满 则 阻 塞 blockingq.put(object); for (;;) { blockingq.take(); // 如 果 队 列 空 则 阻 塞 阻 塞 队 列, 是 一 种 常 用 的 并 发 数 据 结 构, 常 用 于 生 产 者 - 消 费 者 模 式 在 Java 中, 有 三 种 常 用 的 阻 塞 队 列 : ArrayBlockingQueue LinkedBlockingQueue SynchronousQueue
使 用 阻 塞 队 列 Queue<E> add(e) : boolean offer() : boolean remove() : E poll() : E element() : E peek() : E 使 用 BlockingQueue 的 时 候, 尽 量 不 要 使 用 从 Queue 继 承 下 来 的 方 法, 否 则 就 失 去 了 Blocking 的 特 性 了 BlockingQueue<E> put(e) take() : E offer(e, long, TimeUnit) : boolean poll(long, TimeUnit) : E remainingcapacity() drainto(collection<? super E>) : int drainto(collection<? super E>, int ) : int 在 BlockingQueue 中, 要 使 用 put 和 take, 而 非 offer 和 poll 如 果 要 使 用 offer 和 poll, 也 是 要 使 用 带 等 待 时 间 参 数 的 offer 和 poll 使 用 drainto 批 量 获 得 其 中 的 内 容, 能 够 减 少 锁 的 次 数
使 用 阻 塞 队 列 final BlockingQueue<Object> blockingq = new ArrayBlockingQueue<Object>(10); Thread thread = new Thread("consumer thread") { public void run() { for (;;) { Object object = blockingq.poll(); // 杯 具, 不 等 待 就 会 直 接 返 回 handle(object); 1 ; X final BlockingQueue<Object> blockingq = new ArrayBlockingQueue<Object>(10); Thread thread = new Thread("consumer thread") { public void run() { for (;;) { try { Object object = blockingq.take(); // 等 到 有 数 据 才 继 续 handle(object); catch (InterruptedException e) { break; catch (Exception e) { // handle exception ; 2
使 用 阻 塞 队 列 final BlockingQueue<Object> blockingq = new ArrayBlockingQueue<Object>(10); Thread thread = new Thread("consumer thread") { public void run() { for (;;) { try { Object object = blockingq.poll(1, TimeUnit.SECONDS); // 防 止 死 等 if (object == null) { continue; // 或 者 做 其 他 处 理 catch (InterruptedException e) { break; catch (Exception e) { // handle exception ; 3
实 现 一 个 简 单 的 阻 塞 队 列 (1) 通 过 实 现 简 单 的 阻 塞 队 列 来 学 习 并 发 知 识 class BlockingQ { private Object notempty = new Object(); private Queue<Object> linkedlist = new LinkedList<Object>(); public Object take() throws InterruptedException { synchronized (notempty) { if (linkedlist.size() == 0) { notempty.wait(); return linkedlist.poll(); public void offer(object object) { synchronized (notempty) { if (linkedlist.size() == 0) { notempty.notifyall(); linkedlist.add(object); 要 执 行 wait 操 作, 必 须 先 取 得 该 对 象 的 锁 执 行 wait 操 作 之 后, 锁 会 释 放 被 唤 醒 之 前, 需 要 先 获 得 锁 要 执 行 notify 和 notifyall 操 作, 都 必 须 先 取 得 该 对 象 的 锁 未 取 得 锁 就 直 接 执 行 wait notfiy notifyall 会 抛 异 常
实 现 一 个 简 单 的 阻 塞 队 列 (2) class BlockingQ { private Object notempty = new Object(); private Object notfull = new Object(); private Queue<Object> linkedlist = new LinkedList<Object>(); private int maxlength = 10; 通 过 实 现 简 单 的 阻 塞 队 列 来 学 习 并 发 知 识 public Object take() throws InterruptedException { synchronized (notempty) { if (linkedlist.size() == 0) { notempty.wait(); synchronized (notfull) { if (linkedlist.size() == maxlength) { notfull.notifyall(); return linkedlist.poll(); public void offer(object object) throws InterruptedException { synchronized (notempty) { if (linkedlist.size() == 0) { notempty.notifyall(); synchronized (notfull) { if (linkedlist.size() == maxlength) { notfull.wait(); linkedlist.add(object); 分 别 需 要 对 notempty 和 notfull 加 锁 分 别 需 要 对 notempty 和 notfull 加 锁
实 现 一 个 简 单 的 阻 塞 队 列 (3) class BlockingQ { private Lock lock = new ReentrantLock(); private Condition notempty = lock.newcondition(); private Condition notfull = lock.newcondition(); private Queue<Object> linkedlist = new LinkedList<Object>(); private int maxlength = 10; public Object take() throws InterruptedException { lock.lock(); try { if (linkedlist.size() == 0) { notempty.await(); if (linkedlist.size() == maxlength) { notfull.signalall(); return linkedlist.poll(); finally { lock.unlock(); public void offer(object object) throws InterruptedException { lock.lock(); try { if (linkedlist.size() == 0) { notempty.signalall(); if (linkedlist.size() == maxlength) { notfull.await(); linkedlist.add(object); finally { lock.unlock(); 通 过 实 现 简 单 的 阻 塞 队 列 来 学 习 并 发 知 识 一 个 锁 可 以 创 建 多 个 Condition 要 执 行 await 操 作, 必 须 先 取 得 该 Condition 的 锁 执 行 await 操 作 之 后, 锁 会 释 放 被 唤 醒 之 前, 需 要 先 获 得 锁 要 执 行 signal 和 signalall 操 作, 都 必 须 先 取 得 该 对 象 的 锁 注 意 : 未 锁 就 直 接 执 行 await signal siganlall 会 抛 异 常
Monitor 的 理 论 模 型 http://en.wikipedia.org/wiki/monitor_(synchronization) In concurrent programming, a monitor is an object intended to be used safely by more than one thread. The defining characteristic of a monitor is that its methods are executed with mutual exclusion. That is, at each point in time, at most one thread may be executing any of its methods. This mutual exclusion greatly simplifies reasoning about the implementation of monitors compared with code that may be executed in parallel. Monitors also provide a mechanism for threads to temporarily give up exclusive access, in order to wait for some condition to be met, before regaining exclusive access and resuming their task. Monitors also have a mechanism for signaling other threads that such conditions have been met. Monitors were invented by C.A.R. Hoare [1] and Per Brinch Hansen, [2] and were first implemented in Brinch Hansen's Concurrent Pascal language.
ReentrantLock 和 Synchronized Synchronized 是 Lock 的 一 种 简 化 实 现, 一 个 Lock 可 以 对 应 多 个 Condition, 而 synchronized 把 Lock 和 Condition 合 并 了, 一 个 synchronized Lock 只 对 应 一 个 Condition, 可 以 说 Synchronized 是 Lock 的 简 化 版 本 在 JDK 5,Synchronized 要 比 Lock 慢 很 多, 但 是 在 JDK 6 中, 它 们 的 效 率 差 不 多 不 要 在 Lock 和 Condition 上 使 用 wait notiffy notifyall 方 法! Lock 1 0..* Condition lock(); Unlock(); lock(); unlock(); wait(); notify(); notifyall(); synchronzied await(); signal(); signalall(); awati -> wait singal -> notify singalall-> notifyall
使 用 AtomicInteger class Counter { private volatile int count = 0; public synchronized void increment() { count++; 若 要 线 程 安 全 执 行 执 行 count++, 需 要 加 锁 public int getcount() { return count; 1 class Counter { private AtomicInteger count = new AtomicInteger(); public void increment() { count.incrementandget(); 使 用 AtomicInteger 之 后, 不 需 要 加 锁, 也 可 以 实 现 线 程 安 全 public int getcount() { return count.get(); 2 这 是 由 硬 件 提 供 原 子 操 作 指 令 实 现 的 在 非 激 烈 竞 争 的 情 况 下, 开 销 更 小, 速 度 更 快 Java.util.concurrent 中 实 现 的 原 子 操 作 类 包 括 : AtomicBoolean AtomicInteger AtomicLong AtomicReference
使 用 Lock-Free 算 法 class Counter { private volatile int max = 0; public synchronized void set(int value) { if (value > max) { max = value; public int getmax() { return max; 1 若 要 线 程 安 全, 需 要 加 锁 循 环 CAS 回 退 class Counter { private AtomicInteger max = new AtomicInteger(); public void set(int value) { for (;;) { int current = max.get(); if (value > current) { if (max.compareandset(current, value)) { break; else { continue; else { break; public int getmax() { return max.get(); 2 LockFree 算 法, 不 需 要 加 锁 通 常 都 是 三 个 部 分 组 成 : 1 循 环 2 CAS (CompareAndSet) 3 回 退
进 一 步 使 用 Lock-Free 数 据 结 构 class BeanManager { private Map<String, Object> map = new HashMap<String, Object>(); public Object getbean(string key) { synchronized (map) { Object bean = map.get(key); if (bean == null) { map.put(key, createbean()); bean = map.get(key); return bean; class BeanManager { private ConcurrentMap<String, Object> map = new ConcurrentHashMap<String, Object>(); public Object getbean(string key) { Object bean = map.get(key); if (bean == null) { map.putifabsent(key, createbean()); bean = map.get(key); return bean; 使 用 ConcurrentMap, 避 免 直 接 使 用 锁, 锁 由 数 据 结 构 来 管 理 ConcurrentHashMap 并 没 有 实 现 Lock-Free, 只 是 使 用 了 分 离 锁 的 办 法 使 得 能 够 支 持 多 个 Writer 并 发 ConcurrentHashMap 需 要 使 用 更 多 的 内 存
同 样 的 思 路 用 于 更 新 数 据 库 - 乐 观 锁 public class SequenceDao extends SqlMapClientDaoSupport { public boolean compareandset(string name, int value, int expect) { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("name", name); parameters.put("value", value); parameters.put("expect", expect); // UPDATE t_sequence SET value = #value# WHERE name = #name# AND value = #expect# int updatecount = getsqlmapclienttemplate().update("sequence.compareandset", parameters); return updatecount == 1; 通 过 UpdateCount 来 实 现 CompareAndSet public class SequenceService { @Transactional(propagation = Propagation.NOT_SUPPORTED) public synchronized void increment(string sequencename) { for (;;) { int value = dao.getvalue(sequencename); if (dao.compareandset(sequencename, value + 1, value)) { break; 三 个 部 分 : 1 循 环 2 CAS (CompareAndSet) 3 回 退 注 意, 乐 观 锁 时 必 须 使 用 :@Transactional(propagation = Propagation.NOT_SUPPORTED)
对 比, 使 用 悲 观 锁 版 本 public class SequenceDao extends SqlMapClientDaoSupport { public int getvalueforupdate(string name) { // SELECT value FROM t_sequence WHERE name = #name# FOR UPDATE return (Integer) getsqlmapclienttemplate().queryforobject("sequence.getvalueforupdate", name); public void set(string name, int value) { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("name", name); parameters.put("value", value); // UPDATE t_sequence SET value = #value# WHERE name = #name# getsqlmapclienttemplate().update("sequence.set", parameters); public class SequenceService { @Transactional(propagation = Propagation.REQUIRED) public synchronized void increment2(string sequencename) { int value = dao.getvalueforupdate(sequencename); dao.set(sequencename, value + 1); 读 取 时, 就 开 始 加 锁 Lock-Free 算 法, 可 以 说 是 乐 观 锁, 如 果 非 激 烈 竞 争 的 时 候, 不 需 要 使 用 锁, 从 而 开 销 更 小, 速 度 更 快
使 用 CopyOnWriteArrayList class Engine { private List<Listener> listeners = new ArrayList<Listener>(); public boolean addlistener(listener listener) { synchronized (listeners) { return listeners.add(listener); public void doxxx() { synchronized (listeners) { for (Listener listener : listeners) { listener.handle(); 1 class Engine { private List<Listener> listeners = new CopyOnWriteArrayList <Listener>(); public boolean addlistener(listener listener) { return listeners.add(listener); public void doxxx() { for (Listener listener : listeners) { listener.handle(); 2 适 当 使 用 CopyOnWriteArrayList, 能 够 提 高 读 操 作 时 的 效 率
锁 的 使 用 1 使 用 支 持 CAS 的 数 据 结 构, 避 免 使 用 锁, 如 : AtomicXXX ConcurrentMap CopyOnWriteList ConcurrentLinkedQueue 2 3 4 一 定 要 使 用 锁 的 时 候, 注 意 获 得 锁 的 顺 序, 相 反 顺 序 获 得 锁, 就 容 易 产 生 死 锁 死 锁 经 常 是 无 法 完 全 避 免 的, 鸵 鸟 策 略 被 很 多 基 础 框 架 所 采 用 通 过 Dump 线 程 的 StackTrace, 例 如 linux 下 执 行 命 令 kill -3 <pid>, 或 者 jstack l <pid>, 或 者 使 用 Jconsole 连 接 上 去 查 看 线 程 的 StackTrace, 由 此 来 诊 断 死 锁 问 题 5 外 部 锁 常 被 忽 视 而 导 致 死 锁, 例 如 数 据 库 的 锁
并 发 流 程 控 制 - 使 用 CoutDownLatch final int COUNT = 10; final CountDownLatch completelatch = new CountDownLatch(COUNT); for (int i = 0; i < COUNT; ++i) { Thread thread = new Thread("worker thread " + i) { public void run() { // do xxxx completelatch.countdown(); ; thread.start(); completelatch.await(); 当 你 启 动 了 一 个 线 程, 你 需 要 等 它 执 行 结 束, 此 时,CountDownLatch 也 许 是 一 个 很 好 的 选 择 final CountDownLatch startlatch = new CountDownLatch(1); for (int i = 0; i < 10; ++i) { Thread thread = new Thread("worker thread " + i) { public void run() { try { startlatch.await(); catch (InterruptedException e) { return; // do xxxx ; thread.start(); // do xxx startlatch.countdown(); 当 你 启 动 很 多 线 程, 你 需 要 这 些 线 程 等 到 通 知 后 才 真 正 开 始,CountDownLatch 也 许 是 一 个 很 好 的 选 择
Barrer Barrer Barrer Barrier A A A B B B C C C D D D time A barrier: A barrier is a coordination mechanosm (an algorithm) that forces process which participate in a concurrent (or distributed) algorithm to wait until each one of them has reached a certain point in its program. The collection of these coordination points is called the barrier. Once all the processes have reached the barrier, they are all permitted to continue past the barrier.
并 发 流 程 控 制 - 使 用 CycliBarrier class PerformaceTest { private int threadcount; private CyclicBarrier barrier; private int loopcount = 10; public PerformaceTest(int threadcount) { this.threadcount = threadcount; barrier = new CyclicBarrier(threadCount, new Runnable() { public void run() { collecttestresult(); ); for (int i = 0; i < threadcount; ++i) { Thread thread = new Thread("test-thread " + i) { public void run() { for (int j = 0; j < loopcount; ++j) { dotest(); try { barrier.await(); catch (InterruptedException e) { return; catch (BrokenBarrierException e) { return; ; thread.start(); private void dotest() { /* do xxx */ private void collecttestresult() { /* do xxx */ 使 用 Barrier 来 实 现 并 发 性 能 测 试 的 聚 合 点
使 用 定 时 器 ScheduledExecutorService schedule(runnable command, long delay, TimeUnit unit) : ScheduledFuture schedule(callable<v> callable, long delay, TimeUnit unit) : ScheduledFuture scheduleatfixedrate(runnable comand, long initdelay, long period, TimeUnit unit) : ScheduledFuture schedulewithfixeddelay(runnable command, long initdelay, long delay, TimeUnit unit) : ScheduledFuture ScheduledTask Submitter ScheduleFuture<Object> future = scheduler.schedule(task, 1, TimeUnit.SECONDS); // 等 待 到 任 务 被 执 行 完 毕 返 回 结 果 // 如 果 任 务 执 行 出 错, 这 里 会 抛 ExecutionException future.get(); ScheduledExecutorService DelayedWorkQueue Task Task Task Task Task // 取 消 调 度 任 务 future.cancel(); java.util.concurrent.executors 是 ScheduledExecutorService 的 工 厂 类, 通 过 Executors, 你 可 以 创 建 你 所 需 要 的 ScheduledExecutorService JDK 1.5 之 后 有 了 ScheduledExecutorService, 不 建 议 你 再 使 用 java.util.timer, 因 为 它 无 论 功 能 性 能 都 不 如 ScheduledExecutorService
大 规 模 定 时 器 TimerWheel 存 在 一 种 算 法 TimerWheel, 适 用 于 大 规 模 的 定 时 器 实 现 这 个 算 法 最 早 是 被 设 计 用 来 实 现 BSD 内 核 中 定 时 器 的, 后 来 被 广 泛 移 植 到 诸 如 ACE 等 框 架 中, 堪 称 BSD 中 经 典 算 法 之 一, 能 针 对 定 时 器 的 各 类 常 见 操 作 提 供 接 近 常 数 时 间 的 响 应, 且 能 根 据 需 要 很 容 易 进 行 扩 展 7 0 1 2 6 5 4 3
并 发 三 大 定 律 Amdahl 定 律 Gene Amdahl 发 现 在 计 算 机 体 系 架 构 设 计 过 程 中, 某 个 部 件 的 优 化 对 整 个 架 构 的 优 化 和 改 善 是 有 上 限 的 这 个 发 现 后 来 成 为 知 名 的 Amdahl 定 律 Gustafson 定 律 Gustafson 假 设 随 着 处 理 器 个 数 的 增 加, 并 行 与 串 行 的 计 算 总 量 也 是 可 以 增 加 的 Gustafson 定 律 认 为 加 速 系 数 几 乎 跟 处 理 器 个 数 成 正 比, 如 果 现 实 情 况 符 合 Gustafson 定 律 的 假 设 前 提 的 话, 那 么 软 件 的 性 能 将 可 以 随 着 处 理 个 数 的 增 加 而 增 加 Sun-Ni 定 律 充 分 利 用 存 储 空 间 等 计 算 资 源, 尽 量 增 大 问 题 规 模 以 产 生 更 好 / 更 精 确 的 解 即 使 你 有 10 个 老 婆, 也 不 能 一 个 月 把 孩 子 生 下 来 当 你 有 10 个 老 婆, 就 会 要 生 更 多 的 孩 子 你 要 设 法 让 每 个 老 婆 都 在 干 活, 别 让 她 们 闲 着
拜 神 Doug Lea - Mr. concurrency, 当 今 世 界 上 并 发 程 序 设 计 领 域 的 先 驱, 著 名 学 者 他 是 util.concurrent 包 的 作 者,JSR166 规 范 的 制 定 图 书 著 作 Concurrent Programming in Java: Design Principles and Patterns 其 A Scalable Elimination-based Exchange Channel 和 Scalable Synchronous Queues 两 篇 论 文 列 为 非 阻 塞 同 步 算 法 的 经 典 文 章
推 荐 图 书
我 们 今 天 没 有 10GHz 芯 片!
在 IDF05(Intel Developer Forum 2005) 上,Intel 首 席 执 行 官 Craig Barrett 就 取 消 4GHz 芯 片 计 划 一 事, 半 开 玩 笑 当 众 单 膝 下 跪 致 歉
Donald Knuth 世 界 顶 级 计 算 机 科 学 家 在 我 看 来, 这 种 现 象 ( 并 发 ) 或 多 或 少 是 由 于 硬 件 设 计 者 已 经 无 计 可 施 了 导 致 的, 他 们 将 Moore 定 律 失 效 的 责 任 推 脱 给 软 件 开 发 者 Donald Knuth 2008 年 7 月 接 受 Andrew Binstock 访 谈
A Brief History of Time GUIs Introduced Adopted in mainstream 1973 (Xerox Alto) ~1984-89 (Mac) ~1990-95 (Win3.x) Objects 1967 (Simular) ~1993-98 (C++, Java) Garbage Collection 1958 (Lisp) ~1995-2000 (Java) Generic Types 1967 (Strachey) ~198x (US DoD, Ada) ~1995-2000 (C++) Internet 1967+ (ARPAnet) ~1995-2000 Concurrency 1964 (CDC 6600) ~2007-2012
中 国 的 超 级 计 算 机 : 天 河 1 号 1.206P, 星 云 3P, 都 是 异 构 计 算 体 系
AMD Radeon HD 5970 Radeon HD 5970 $299 单 精 度 浮 点 处 理 能 力 双 精 度 浮 点 处 理 能 力 核 心 频 率 处 理 器 核 心 数 量 内 存 类 型 显 存 容 量 最 大 功 耗 显 存 带 宽 4.64 TFLOPS 928 GFLOPS 725 MHz 3200 GDDR5 4 GB 294 W 256 GB/sec 37
GPU 大 规 模 并 行 计 算
Processor Parallelism CPUs Multiple cores driving performance increases Multi-processor programming e.g. OpenMP Emerging Intersection OpenCL Heterogenous Computing GPUs Increasingly general purpose data-parallel computing Improving numerical precision Graphics APIs and Shading Languages OpenCL Open Computing Language Open, royalty-free standard for portable, parallel programming of heterogeneous parallel computing CPUs, GPUs, and other processors
适 用 的 应 用 范 围 CPU GPU 潜 在 操 作 系 统 递 归 算 法 桌 面 应 用 例 如 MS Word 交 互 性 应 用 例 如 Debugger 热 点 油 气 勘 探 金 融 分 析 医 疗 成 像 有 限 元 基 因 分 析 物 理 模 拟 地 理 信 息 系 统 搜 索 引 擎 数 据 库 数 据 挖 掘 数 理 统 计 分 析 生 物 医 药 工 程 导 航 识 别 军 事 模 拟 无 线 射 频 模 拟 图 像 语 音 识 别
内 容 回 顾 1 使 用 线 程 的 经 验 : 设 置 名 称 响 应 中 断 使 用 ThreadLocal 2 Executor :ExecutorService 和 Future 3 阻 塞 队 列 : put 和 take offer 和 poll drainto 4 线 程 间 的 协 调 手 段 :lock condition wait notify notifyall 5 Lock-free: atomic concurrentmap.putifabsent CopyOnWriteArrayList 6 关 于 锁 使 用 的 经 验 介 绍 7 并 发 流 程 控 制 手 段 :CountDownlatch Barrier 8 定 时 器 : ScheduledExecutorService 大 规 模 定 时 器 TimerWheel 9 并 发 三 大 定 律 :Amdahl Gustafson Sun-Ni 10 神 人 和 图 书 11 业 界 发 展 情 况 : GPGPU OpenCL
复 习 题 请 回 答 以 下 问 题 : 1. Future 是 做 什 么 用 的? 2. Lock 和 synchronized 的 区 别 是 什 么? 3. 什 么 是 CAS? 4 Lock-Free 算 法 的 三 个 组 成 部 分 是 什 么?
谢 谢!