Java 线程安全
2020-04-09 本文已影响0人
BestFei
一、堆内存与线程安全
在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。
线程安全指的是,在堆内存中的数据由于可以被任何线程访问到,在没有限制的情况下存在被意外修改的风险。
二、解决
1、私有变量
操作系统会为每个线程分配属于它自己的内存空间,通常称为栈内存,其它线程无权访问。
也就是说局部变量会在每个线程的栈内存中都分配一份。由于线程的栈内存只能自己访问,所以栈内存中的变量只属于自己,其它线程根本就不知道。
2、公有变量
要让公共区域堆内存中的数据对于每个线程都是安全的,那就每个线程都拷贝它一份,每个线程只处理自己的这一份拷贝而不去影响别的线程的,即ThreadLocal类。
线程类(Thread)有一个成员变量,类似于Map类型的,专门用于存储ThreadLocal类型的数据。
这些ThreadLocal数据是属于Thread类的成员变量级别,分配在公共区域的堆内存中的。
把堆内存中的一个数据复制N份,每个线程认领1份,同时规定好,每个线程只能玩自己的那份,不准影响别人的。
3、设置 final ,只能读取,不能修改。
4、(互斥)锁 【悲观锁】
class ClassAssistant {
double totalScore = 60;
final Lock lock = new Lock();
void addScore(double score) {
lock.obtain();
totalScore += score;
lock.release();
}
void subScore(double score) {
lock.obtain();
totalScore -= score;
lock.release();
}
}
5、CAS(Compare And Swap)【乐观锁】
在并发很小的情况下,数据被意外修改的概率很低,但是又存在这种可能性,此时就用CAS。
即发现数据被修改,就放弃,然后从头再来。