1、线程内存访问机制
当线程访问某个对象的值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。
2、volatile关键字
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值,正确使用volatile的条件:
1)对变量的写操作不依赖于当前值(read-modify-write)
2)不能和其他变量同时在一个表达式中
正确使用volatile的几种情况:
1)状态标志:boolean类型的状态标志
2)一次性完全发布:被发布的对象必须是线程安全的或有效的不可变对象
3)独立观察:定期发布观察结果供内部使用,要求被发布的值是有效不可变的
4)volatile bean模式:JavaBean 的所有数据成员都是volatile类型的,并且除了getter 和 setter 方法外,不能包含任何逻辑
注:完全发布:即确保对象引用和状态对其他线程正确可见,发布方式:
1)静态初始化器初始化对象引用
2)将引用存储到volatile域
3)将引用存储到正确创建对象的final域
4)将引用存储到由锁正确保护的域
对象完全构造:在对象构造期间,不要公布this引用;不要隐式地暴露“this”引用;不要从构造函数内启动线程
3、synchronized关键字
线程同步的内部机制,通过加锁的方式保证线程的可见性和互斥性,即一个线程的执行结果可以被另一个线程所看到且在同一时间只能有一个线程执行被保护的代码块
4、ThreadLocal
使用ThreadLocal维护的变量,为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
ThreadLocal采用“以空间换时间”的方式解决多线程的并发访问,方法:
1)protected T initialValue():返回此线程局部变量的当前线程的“初始值”;通常,此方法对每个线程最多调用一次,但如果在调用 get()后又调用了 remove(),则可能再次调用此方法;默认情况下返回null,如果要返回其他值,需要重写该方法
2)public T get():返回此线程局部变量的当前线程副本中的值
3)public void set(T value):将此线程局部变量的当前线程副本中的值设置为指定值
4)public void remove():移除此线程局部变量当前线程的值