zoukankan      html  css  js  c++  java
  • 十一、并发安全

    并发安全

    【1】什么是类的线程安全?

    ​ 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

    【2】线程不安全引发的问题

    死锁
    死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

    ​ 解决:保证加锁的有序性

    动态顺序死锁

    动态顺序死锁是在实现时按照某种顺序加锁了,但是因为外部调用的问题,导致无法保证加锁顺序而产生的。

    解决方法:

    1)通过内在排序,保证加锁的顺序性(使用identityHashCode获得原生的hashcode,按照这个的hashcode大小制定加锁顺序);

    2)通过显示锁tryLock()进行尝试拿锁

    活锁

    尝试拿锁的机制中,发生多个线程之间互相谦让,不断发生拿锁,释放锁的过程。

    解决办法:每个线程休眠随机数,错开拿锁的时间。

    线程饥饿

    【3】怎么才能做到类的线程安全?

    栈封闭
    所有的变量都是在方法内部声明和使用,这些变量都处于栈封闭状态。

    无状态类

    没有任何成员变量的类,就叫无状态的类

    让类不可变

    让类不可变有两种方法:

    • 加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的成员变量应该加上final关键字,但是加上final,要注意如果成员变量又是一个对象的引用时,这个对象所对应的类也要是不可变,才能保证整个类是不可变
    • 不提供修改成员变量的方法,同时成员变量也不作为方法的返回值

    volatile

    保证类的可见性,最适合一个线程写,多个线程读的情景

    对于写,可以使用Synchronized加锁等效为一个线程写

    加锁和CAS

    详情见往期博客

    安全的发布

    类中持有的成员变量,特别是对象的引用,如果这个成员对象不是线程安全的,通过get等方法发布出去,会造成这个成员对象本身持有的数据在多线程下不正确的修改,从而造成整个类线程不安全的问题。

    解决方法:

    • 用线程安全的容器替换
    • 返回副本,深拷贝
    • 加锁

    TheadLocal

    详情见往期博客

    【4】线程安全的单例模式

    饿汉式

    • 在声明的时候就new这个类的实例,因为在JVM中,对类的加载和类初始化由虚拟机保证线程安全。
    public class SingletonHungry {
        public static SingletonHungry singletonHungry = new SingletonHungry();
        private SingletonHungry(){}
    }
    
    • 或者使用枚举。

    懒汉式
    在单例类的内部由一个私有静态内部类来持有这个单例类的实例。

    public class SingletonLazy {
        private SingletonLazy(){}
    
        //定义一个私有类,来持有当前类的实例
        private static class InstanceHolder{
            public static SingletonLazy instance = new SingletonLazy();
        }
    
        public static SingletonLazy getInstance(){
            return InstanceHolder.instance;
        }
    }
    
  • 相关阅读:
    Leetcode Plus One
    Leetcode Swap Nodes in Pairs
    Leetcode Remove Nth Node From End of List
    leetcode Remove Duplicates from Sorted Array
    leetcode Remove Element
    leetcode Container With Most Water
    leetcode String to Integer (atoi)
    leetcode Palindrome Number
    leetcode Roman to Integer
    leetcode ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/lee0527/p/11723051.html
Copyright © 2011-2022 走看看