可见性
在不同线程对同一个对象的读写操作时,线程的可见性显得尤为的重要,为了确保多个线程之间对内存的写入操作的可见性,必须使用同步机制,因为我们没法确保执行读操作的线程能实时的读取到写操作线程刚刚写入的值。

同步机制:

java 用户共享 java共享对象_数组



对于上图的同步机制,可以使用volatile关键字来修饰对象实现,但并不推荐,因为它不能完全的保证对象的线程安全,他是java语言提供的一种轻量的、稍弱的同步机制;volatile变量对可见性的影响比volatile变量本身更加重要。当线程A首先写入一个volatile变量并且线程B随后读取该变量时,在写入volatile变量之前对A可见的所有变量的值,在B读取了volatile变量之后,对B也是可见的。因此,从内存的角度来说,写入volatile变量相当与退出了同步代码块,而读取volatile变量的值相当与进入了同步代码块。然后,我们并不建议过度依赖volatile变量提供的可见性。如果在代码里通过volatile变量来控制状态的可见性,通常比使用锁更加的脆弱,也更加难以理解!

对象的发布和溢出
发布:使对象能在当前作用域之外的代码处使用;
溢出:对某个不应发布的对象进行发布的时候,就称溢出;
溢出会破坏程序的封装性,导致程序变的难以维护,一个非线程安全的内部对象溢出后,会破坏线程的安全,导致意想不到的后果!

java 用户共享 java共享对象_数组_02


如上图这样发布一个数组,任何调用者都可以修改这个数组的内容,在这里,数组states已经逾越了它的作用范围了,因为这个本应该是私有的变量被发布了。

最后一个发布要注意的是,不要在构造中,通过内部类的方式,隐式的发布一个this引用!

java 用户共享 java共享对象_可见性_03


上面例子中,注册监听的时候,创建了一个匿名内部类,在这个匿名内部类中,隐式的包含了ThisEscape的this引用,使得在这个匿名内部类中可以访问和修改ThisEscape的作用域。可以通过工厂模式来解决这个问题:

java 用户共享 java共享对象_java 用户共享_04



线程封闭
线程封闭是指将一些共享的对象,基于安全考虑,感觉全部封闭在线程内,不让其他线程访问,通过避免使用同步技术来达到不共享数据的方式;比较合理的封闭有两种,一种是栈封闭,还有一种是JDK提供的更加规范的方式,使用ThreadLocal类来完成;

栈封闭:
栈封闭是线程封闭的一种特例,在栈封闭中,只有通过局部变量才能访问对象。