zoukankan      html  css  js  c++  java
  • Java并发编程实践——读书笔记(一)

    Java并发编程实践——读书笔记(一)

    《Java Concurrency in Practice》第一部分的阅读总结

    关键字:并发、锁、线程安全、共享对象、并发容器、信号量

    目录

    第一章 介绍

    1.1 并发的简短历史

    1.2 线程的优点

    ​ 1.3 线程的风险

    1.4 线程无处不在

    第二章 线程安全

    ​ 2.1 什么是线程安全性

    ​ 2.2 原子性

    ​ 2.3 锁

    ​ 2.4 用锁来保护状态

    2.5 活跃度与性能

    ​ 第三章 共享对象

    ​ 3.1 可见性

    ​ 3.2 发布和逸出

    ​ 3.3 线程封闭

    ​ 3.4 不可变性

    3.5 安全发布

    ​ 第四章 组合对象

    4.1 设计线程安全的类

    4.2 实例限制

    4.3 委托线程安全

    4.4 向已有的线程安全类添加功能

    4.5 同步策略的文档化

    ​ 第五章 构建块

    ​ 5.1 同步容器

    ​ 5.2 并发容器

    ​ 5.3 阻塞队列

    5.4 阻塞和可中断的方法

    ​ 5.5 Synchronizer

    5.6 为计算结果建立高效、可伸缩的高速缓存

    第一章

    • 线程的风险

      • 竞争场景(race condition)

        多个线程并发地对共享数据进行操作

      • 活跃度失败(liveness failure)(程序无法继续执行或退出)

        如果安全意味着”什么坏事都没有发生“,那么活跃度关注的则是”好事最终发生了“

      • 性能危险(performance)

        ...,线程仍然会给运行时带来一定程度的开销。上下文切换(Context switches) ,...,这在多个线程组成的应用程序中是很频繁的,并且带来巨大的系统开销。...,CPU的时间会花费在对线程的调度上而不是在运行上。

    第二章

    • 线程的安全性

      正确性意味着一个类与它的规约保持一致。良好的规约定义了用于强制对象状态的不变约束(invariants)以及描述操作影响的后验条件(postcoditions)

      一个类是线程安全的,是指在被多个线程访问时,类可以持续进行正确的行为

    • 原子性

      假设有操作A和B,如果从执行A的线程的角度看,当其他线程执行B的时候,耀目B全部执行完成,要么一点都没执行,这样A和B互为原子操作

      • Java.uitl.concurrent.atomic包中包括了原子变量类(atomic variable),这些类实现了数字和对象引用的原子转换(该对象的操作都是原子的)

        • AtomicLong(基本类型对应的原子对象)
        • AtomicReference<V>(一些对象引用对应的原子对象)
      • 复合操作——”读-改-写“和”检查再运行“

        • 这是两类常见的看似原子,但是却不是原子的操作。读改写对应赋值语句,检查再运行对应条件判断
      • 内部锁

        • synchronized(锁对象的引用,锁代码块)
        • 方法级别的synchronized,锁对象是方法的调用者。静态方法的synchronized,锁对象是对应的调用者对象的class对象
        • 内部锁是一种互斥锁,至多只有一个线程可以拥有锁,但是内部锁是可重入的。
      • 重进入(Reentrancy)

        线程在试图获得它自己占优的锁的时候,如果请求成功,那么该锁是可重入的。

    • 锁对状态的保护

      对于每个可被多个线程访问的可变状态变量,如果所有访问它的线程在执行时都占有同一个锁,这种情况下,我们称这个变量是由这个锁保护的

      • 内部锁只能确保一件事,一个线程获得对象的锁之后,将阻塞其他线程获得这个锁
      • Vector 和Hashtable
        • 通过使用对象的内部锁(synchronized关键字)来封装所有的可变状态

      对于每一个涉及多个变量的不变约束,需要同一个锁保护其他所有的变量

    第三章

    • 可见性(defined)

      在没有同步的情况下,编译器、处理器,运行时安排操作的执行顺序可能完全出入意料。在没有进行适当同步的多线程程序中,尝试推断那些”必然"发生在内存中的动作,你总会判断错误。

      可见性保证了,内存中的值是已定义的(也就是能够判断出来的),可能听着还是有些抽象。举个例子,多个线程对一个64位的long long变量进行值的修改,那么可能线程A正在修改变量的高32位地址,而线程B在修改变量的低32位地址,这样最后的产生的值就是undefined,也就是无法判断的。

      • 可见性比并发的要求弱, 意味着数据可能过期

      • Volatile

        • 轻量级的同步机制
        • 只保证了对应变量引用的内存是“可见的”,不保证数据同步 。
          • 从主存读,并且写入内存。(不存在cpu寄存器中,性能损失)
      • 锁不仅仅是关于同步与互斥的,也是关于内存可见的。为了保证所有线程都能够看到共享的、可变变量的最新值,读取和写入线程必须使用公共的锁进行同步

    • 对象的发布与逸出(publishing & escape)

      • 发布:使它能够被当前范围之外的代码所使用
        • 将对象的引用存储到公共静态域中
        • 从非私有方法中返回引用
        • 发布一个对象,同样也发布了该对象所有非私有域所引用的对象
      • 逸出:未经计划的发布
    • 线程封闭

      • 局部变量

      • ThreadLocal类

        ThreadLocal允许你将每个线程与持有数值的对象关联在一起。ThreadLocal提供了get和set访问器,为每个使用它的线程维护一份单独的拷贝。所以get总是返回由当前执行线程通过set设置的最新值。

        本质是全局设置一个容器,通过判断currentThread,然后存入容器中来实现。

      • 单一线程对Volatile变量进行写操作。

    • 不可变性(不可变对象)

      • 不可变对象:只有访问器方法,可变状态被封装
      • 不可变对象永远是线程安全的(可变对象的final引用,不叫不可变

    第五章

    • 同步容器

      • Vector和Hashtable

      • Collections.synchronizedXxx(Xxx xxx)方法创建的同系列,如:

        List t = Collections.synchronizedList(new ArrayList()) ;
        
      • 不要轻易使用/隐藏使用同步容器的toString方法,由于被synchronized关键字修饰,串行,所以可能非常耗时。

    • 并发容器

      同步容器通过对容器的所有状态进行串行访问,从而实现了它们的线程安全。这样做的代价是削弱了并发性。并发容器就是在此基础上进行了设计,牺牲了部分的同步性来换取并发性能。

      • Queue
        • BlockingQueue
          • LinkedBlockingQueue
          • ArrayBlockingQueue
          • PriorityBlockingQueue
          • SynchronousQueue
        • ConcurrentLinkedQueue
        • Deque
          • ArrayDeque
          • LinkedBlockingDeque
      • Map
        • ConcurrentHashMap—— Hashtable/ synchronizedMap
        • ConcurrentSkipListMap ——synchronizedSortedMap
      • Set
        • ConcurrentSkipListSet —— synchronizedSortedSet
      • List
        • CopyOnWriteArrayList —— synchronizedList
          • 读不同步,写同步
    • 阻塞队列(Blocking Queue) & 生产者-消费者模式

      • 阻塞队列天然支持生产者-消费者模式
      • Deque与窃取模式
    • Synchronizer(同步器)

      • latch(闭锁)
        • 同步开始与结束
      • semaphore(信号量)
        • 实现阻塞队列
      • barrier(关卡)
        • cycle
  • 相关阅读:
    Nginx出现10055错误问题
    MVC报错的坑
    用Docker运行一个简单RazorDemo(一)
    dotnet run
    用Docker 在Centos7上部署Core2.1网站
    VS2015 自己用的插件
    帐户当前被锁定,所以用户 sa 登录失败。系统管理员无法将该帐户解锁
    加密方法汇总
    【备用】网页抓取、
    【转】项目奖金分配
  • 原文地址:https://www.cnblogs.com/backkom-buaa/p/13353497.html
Copyright © 2011-2022 走看看