美文网首页
java多线程(七)并发安全

java多线程(七)并发安全

作者: 7ColorLotus | 来源:发表于2020-05-26 22:54 被阅读0次
    • 类的线程安全定义

      1. 如果在多线程下使用这个类,不管这个多线程如何使用和调度这个类,这个类总是表现出正确的行为,这个类就是线程安全的
      2. 如何线程安全
        1> 操作的原子性
        2> 内存的可见性
      3. 会在多个线程之间共享状态的时候,就会出现线程不安全
    • 怎么才能做到类的线程安全

      1. 栈封闭
        1> 定义在方法内部的局部变量,这些变量都处于栈封闭状态
      2. 无状态
        1> 没有任何成员变量的类就叫无状态的类
      3. 让类不可变
        1> 加final关键字。让状态不可变,对一个类,所有的成员变量是私有的,同样的只要有可能,所有的成员变量应该加上final关键字
        2> 根本不提供任何可供修改成员变量的地方,同时成员变量也不作为方法返回值
      4. 加锁和CAS
      5. 安全的发布
        1> 用线程安全的容器替换
        2> 要么发布出去的时候,提供副本,深度拷贝
      6. ThreadLocal
      7. volatile
        1> 保证类的可见性,最适合一个线程写,多个线程读的情景
    • Servlet

      1. 不是线程安全的类,在需求上,很少有共享的需求
      2. 接收到了请求,返回应答的时候,都是由一个线程负责
    • 死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或者彼此通信造成一种阻塞的现象,若无外力,它无法进行下去。此时称系统出现了死锁状态

      1. 竞争资源多余一个,同时小于等于竞争的线程数。资源只有一个只会产生竞争激烈,不会产生死锁
      2. 通过系统手动解决死锁
        1>jps常看死锁id
        2>jstack id常看应用的死锁情况
      3. 有哪些死锁
        1>发生死锁时,获取锁的顺序不一致。譬如两个线程A和B,需要锁定两个资源C和D,A线程依次锁定C和D,B依次锁定D和C。多次同步执行时就可能造成死锁
        2>动态顺序死锁,顺序不确定。譬如两个线程A和B,需要锁定两个资源C和D,A线程依次锁定C和D,B依次锁定C和D。但是B有可能先锁定C再锁B的情况。
        多次同步执行时就可能造成死锁。
      4. 程序避免死锁
        1>解决方法1:比较hashcode,分别加锁。System.identityHashCode()获取对象的最原始的hashCode,同一个对象的一定相同
        2>解决方法2:使用显示锁,尝试拿锁,tryLock
      5. 锁的内存语义


        锁的内存语义.png
    • 活锁

      1. 使用tryLock的时候,线程之间谦让,一个线程拿到一个锁,进行操作后,再拿另一个锁的时候拿不到会退出锁。重新进入锁。
      2. 解决方法:添加睡眠时间,错开锁的时间
    • 线程饥饿

      1. 一个低优先级的线程,总是拿不到执行时间
    • 性能和思考

      1. 使用多线程的目标是为了提高性能,引入多线程后,同时会引入额外的开销.
      2. 衡量应用程序的性能:服务时间和延迟时间(处理速度,多快),吞吐量(处理能力的指标,完成工作的多少),可伸缩性
      3. 多快和多少,完全独立,甚至相互矛盾
      4. 对服务器应用来说,多少(可伸缩性,吞吐量)这个方面比多快更受重视
      5. 做应用的时候
        1>先保证程序正确,确实达不到要求的时候,再提高速度
        2>一定要以测试为基准
      6. 一个应用程序里,串行的部分是永远都有的。Amdahl定律:1/(F+(1-N)/N)。 F:必须被串行部分,程序最好的结果:1/F
    • 影响性能的因素

      1. 上下文的切换
        1>一次切换5000-10000个时钟周期,几微秒
      2. 内存同步
        1>加锁,增加额外的指令
      3. 阻塞
        1>挂起,包括两次额外的上下文切换
    • 减少锁的竞争

      1. 缩小锁的范围:对锁的持有,快进快出,尽量缩短持有的时间
      2. 避免多余的锁减锁的范围
      3. 减小锁的粒度:使用锁的时候,锁所保护的对象是多个,多个对象之间其实是独立变化的时候,不如用多个锁来一一保护这些对象。但是要注意避免发生死锁
      4. 锁分段(ConcurrentHashMap)
      5. 替换独占锁:1>使用读写锁 2>使用CAS 3>使用系统并发容器
    • 单例模式

      1. 双重检查的懒汉式
        1>安全问题:对象的引用有了,对象的域没有填充完成。
        2>解决方法:对类元素添加volatile修饰符
      2. 饿汉式:在JVM中,对类的加载和初始化,由虚拟机保证线程安全
      3. 懒汉式:延迟占位模式

    相关文章

      网友评论

          本文标题:java多线程(七)并发安全

          本文链接:https://www.haomeiwen.com/subject/izbbahtx.html