一、问题
多线程操作共享变量,共享变量为引用类型,出现引用类型值出现改变的问题。
二、基本数据类型和引用数据类型在内存中的对比
对比 | 基本数据类型 | 引用数据类型 |
---|---|---|
存储地址 | 在栈中进行分配 | 在堆中进行分配,堆的读写速度远不及栈 |
指针指向 | 变量名指向具体的数值 | 变量名指向存数据对象的内存地址,即变量名指向hash值 |
初始化 | 变量在声明之后java就会立刻分配给他内存空间 | 它以特殊的方式(类似C指针)指向对象实体(具体的值),这类变量声明时不会分配内存,只是存储了一个内存地址 |
复制 | 基本类型之间的赋值是创建新的拷贝 | 对象之间的赋值只是传递引用 |
判断相等 | ==是在比较值 | ==是在比较两个引用是否相同,需要自己实现equals()方法 |
销毁 | 基本类型变量创建和销毁很快 | 类对象需要JVM去销毁 |
三、 解决思路
1、引用类型保证线程安全的常用方法
- 尽量不要跨线程访问共享变量,因为多线程操作同一个变量,可能因为线程不可见出现线程安全问题,或者出现共享变量的改变导致业务逻辑出现问题。
- 将共享变量定为final类型的,如果对于多个线程需要保证共享变量不会随着某个线程的改变导致其他线程接收参数出现改变可以添加final。
- 将共享变量的操作加上同步。
- 引用类型的某个值可以使用CAS进行判断。
2、基本类型保证线程安全的常用方法
查看 CAS机制以及AtomicXXX和Unsafe的实现。
3、容器保证线程安全的常用方法
查看 java安全性容器。