线程安全问题
线程安全问题本质上就是内存安全问题。
每个进程中都会有一块特殊的区域(堆内存),进程中所有线程都可以访问该区域,这是线程安全问题的原因之一。
线程安全指的是,在堆内存中的数据由于可以被所有线程访问到,在没有限制措施的条件下存在被意外修改的风险。
解决方式
1、操作系统会给每个线程分配私有空间(栈内存),栈内存中的数据只能被线程本身访问,其他线程无权访问,因此可以将可能会发生线程安全的数据放到栈内存中,常见的是在程序中定义为局部变量。
优点:安全
缺点:局部变量访问权限变小
2、将数据放在公共区域(堆内存)中,当每个线程使用时都拷贝一份数据在自己的栈内存中,只操作自己栈内存中的数据。也就是使用ThreadLocal类。
优点:安全
缺点:*
3、将公共区域的数据使用final关键字修饰,这样线程只能读取,不能修改。
优点:安全
缺点:只能读,不能改
4、将数据放在堆内存中,每个线程在获取到数据的使用权时,对该数据加互斥锁,其他线程看见数据被锁住只能选择等待,当线程使用完毕数据后,释放锁,其他线程才能继续抢夺数据的使用权(悲观锁)。
优点:安全
缺点:获取锁释放锁需要消耗资源
5、CAS(Compare And Swap):假设程序并发量很小,造成线程安全的问题的概率也很小,可以使用CAS方式,规定一个版本号,如果A线程操作数据未操作完毕就去做其他工作(此时版本号为2),回来后版本号如果改变就重新从头开始操作,否则就继续完成剩下的工作。(乐观锁)
优点:省去了释放锁获取锁的资源消耗
缺点:不适用于并发量大的程序。