关于线程安全学习笔记

1、什么是线程安全

线程安全不是线程的安全,而是堆内存的安全

在堆内存中的数据由于可以被任何线程访问到,在没有限制的情况下存在被意外修改的风险

即堆内存空间在没有保护机制的情况下,对多线程来说是不安全的地方,因为你放进去的数据,可能被别的线程“破坏”

2、实现线程安全的解决方案

位置:定义私有变量,仅本线程可访问 保障线程安全

复制:ThreadLocal,线程本地,每个线程拷贝一份数据到在自己线程下,实现互不干扰 

class StudentAssistant {

    ThreadLocal<String> realName = new ThreadLocal<>();
    ThreadLocal<Double> totalScore = new ThreadLocal<>();

    String determineDegree() {
        double score = totalScore.get();
        if (score >= 90) {
            return "A";
        }
        if (score >= 80) {
            return "B";
        }
        if (score >= 70) {
            return "C";
        }
        if (score >= 60) {
            return "D";
        }
        return "E";
    }

    double determineOptionalcourseScore() {
        double score = totalScore.get();
        if (score >= 90) {
            return 10;
        }
        if (score >= 80) {
            return 20;
        }
        if (score >= 70) {
            return 30;
        }
        if (score >= 60) {
            return 40;
        }
        return 60;
    }
}

Final:  只能看不能摸,只能读取,不能修改。其实就是常量或只读变量

class StudentAssistant {
    final double passScore = 60;
}

加锁:悲观锁,即默认所有都可能出现线程安全,加锁,其他线程若修改需取到锁 查锁状态,锁未释放只能等候或处理转而处理其他问题

 1 class ClassAssistant {
 2 
 3     double totalScore = 60;
 4     final Lock lock = new Lock();
 5 
 6     void addScore(double score) {
 7         lock.obtain();
 8         totalScore += score;
 9         lock.release();
10     }
11 
12     void subScore(double score) {
13         lock.obtain();
14         totalScore -= score;
15         lock.release();
16     }
17 }

CAS: 乐观锁,即默认都会出现线程安全问题,防止ABA问题,加上 版本号,对比当前数据与线程取到的数据,版本号未变线程数安全数据未修改,否则放弃重来

3、引用大神总结:

前两种属于隔离法,一个是位置隔离,一个是数据隔离。

然后两种是标记法,一个是只读标记,一个是加锁标记。

最后一种是大胆法,先来怼一把试试,若不行从头再来。

参考文档 https://www.cnblogs.com/lixinjie/p/10817860.html

原文地址:https://www.cnblogs.com/0819lsl/p/11009727.html