最近重新读java concurrency in practice 随笔
觉得自己在并发编程还缺很多, 最近一段时间都在积极的学习中。 呵呵, 学到老, 活到老。?
Java 的并发编程涉及的方面还是非常多的:
1, ?基础方面的: 对象的共享。 依照从安全性从高到低的方式 可以有
?
? ? ?最安全的对象共享就是不享, 一个对象仅仅局限在一个线程中。 如果一个对象只能被某个线程的局部变量 也就是在 栈(stack) 访问。? ? ?ThreadLocal 也是一种非常安全的方式? ? ?不可变对象 ?也就是对象的所有域都是final , 并且对象在建构函数中并没有this 指针的逃逸问题。? ? ? 普通对象 ? ?所有在线程之间并发 read/write 的方法都通过锁 来保护。?
? ? 接下来是并发编程会用到得一些常用的并发容器, 队列, 同步工具什么的
?
? ? ? ? 并发容器 ? ConcurrentHashMap, ?CopyOnWriteArrayList? ? ? ? 并发编程中最常用的生产者/ 消费者模式中常用的 ConcurrentLinkedQueue, ?LinkedBlockingDeque。 如果要Queue 的队列大小有限的话都会涉及到 blocking 的问题。 在队列已满的情况下 再朝queue 里面插入元素会让当前线程 wait。? ? ? ?常用的同步工具 ?各种 Latch, ?Semaphore, Barrier。 CountDownLatch 是最常用的一种Latch, 设置一个初始值。需要等待的线程调用 await 方法, 其它线程可以 调用 countDown 来递减这个计数器。 当counter 到 0了, 所有等待这个Latch的线程都会被唤醒。 ?2, 并发程序的结构
? ? ? 2.1, ?Callable/ ?Future
? ? ? ? ? ? ?Runnable 的局限是没有返回值,
?
interface Callable<R> {R call() throws Exception}
? ? ? ? ? ? ?不光是有了返回值, 还有 Exception。?
?
? ? ? ? ? ? Future 表示了一个异步调用的结果
?
? ? ? public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
?
? ? ? ? ? ? 这个接口的实现通常是 ?get 方法只有在 isDone 的时候才马上返回, 否则它会等待。 但是有了这个Future 可以将运行线程的Callable 结果安全的传递给另外一个线程。 ?
?
? ? ? 2.2, ?Execotor ?执行框架
在JDK的 ?java.utility.concurrency (JUC) 包中 定义了?Execotor ?这个仅仅有一个execute 方法, 另外ExecutorService 接口扩展了它。 不仅提供了管理life cycle 的方法外, 还包括了 submit ?Runnable, submit ?Callable 的方法。 ?另外 invokeAll, ?timeout 版的invokeAll 也是非常有用的。 ?
?
?
? ? ? 2.3, ?取消, 中断 , stop
? ? ? ? ? ? ? ? service,生命周期的安全性也是非常重要的。?
?
? ? ? 2.4, 线程池
? ? ? ? ? ? ? ?ThreadPoolExecutor
? ? ? ? ? ? ? JUC 的Executors 工厂类提供了几个非常有用的ExecutorService
? ? ? ? ? ? ? ? ? ? ? ?newFixedThreadPool ?固定线程数目的线程池
? ? ? ? ? ? ? ? ? ? ? ?newSingleThreadExecutor 创建单线程的Executor ?一个线程来run 所有的task , 这样不会有撒并发的问题
? ? ? ? ? ? ? ? ? ? ? ?newScheduledThreadPool ? 可以 schedule commands。有了这个Service 可以忘掉以前的Timer 了。
?
?
3, ?高级主题
? ? ? ?1, ?减少锁的竞争
? ? ? ? ? ? ? 一些常用的手段无非是尽量少用 锁, ?降低锁的粒度, ?降低锁的访问。?
?
? ? ? ?2, ?instrinsic 锁 与 ReentrantLock 的比较
? ? ? ? ? ? ? ? ? instrinsic logic ?也就是 synchronized 的关键字的运用 主要借助java 中 任何一个Object 都有一个wait 队列。 ? 这个synchronized?用的时候 锁的获取与释放必须在同一个block 或者方法中。?
? ? ? ? ? ? ? ? ?ReentrantLock?就比较自由, 但是比较担心没有 unlock, 因此永远不要忘了 try/finally 的方式来用它。
? ? ? ? ? ? ? ? ?ReentrantLock 可以做到 tryLock, ?甚至可以用 timeout 方式在限定时间来获取锁。 ?
? ? ? ? ?ReentrantLock? 可以选择 fair /unfair 方式
? ? ? ? ? ? ? ? ?ReentrantLock? 等待的线程还可以响应 interrupt 。
? ? ? ?3, ?怎样自定义新的同步工具
怎么来借助现有的工具来定制自己有用的新的工具。这块做的还不多, 以后再仔细琢磨吧。? ? ? ? ? ? ??
?
? ? ? ?4, ?非阻塞机制
? ? ? ? ? ? ? 借助硬件的 CAS 也就是 comare and swap 。 如果比较成功再交换, 这整个动作都是 原子操作。 ?原理跟数据库中的 乐观锁的概念是一致的。 先拿出要操作的东西的当前值, 修改它。 在提交的时候 新值和老值都作为参数传入。 ?CAS 比较 传入的old value 与当前值做比较, 如果相同证明没有其它线程操作。否则直接返回false。?
?
? ? ? ? 5, Java 内存模型 ?也就是JSR 133 里面的东东。主要涉及的有 ?re-order, ?volatile, final, ?happen-first 。 这个刚刚看过就略过。 ?它有提到 讲得比较多的 double lock 机制来实现 延迟创建 单例。 ?在新的 1.6 里面的 jvm 里面应该不会再 有什么 java 对象内存分配了 建构函数还在执行 就返回非null 的情况吧。 保险起见就用 JMM 里面明确的 happen-before 机制 像final 域的 initializer,内部static 类 的加载 应该都可以保证安全。 ?安全第一,呵呵。
?
?
暂时就这么多料, ?中英文版本配合起来看 效果还可以。 ?机械工业出版社出版的那个中译本太水了, 很多时候得看英文版, ?毕竟在Kindle DXG 看英文版没有实体中文书方便。 ?
?