java并发编程实践之对象的共享

3.1.可见性
synchronized除了用于操作的原子性之外,还有更加重要的作用,可见性。内存可见性:当某个线程修改某状态时,其他线程不要读写或者修改该状态,并且当线程修改好状态后,其他线程都能在内存中看到该状态的改变。
java并发编程实践之对象的共享_第1张图片
图一
如果并发正确的话,主线程启动读线程,主线程对number,ready赋值后,读线程读到ready=true,并最后打印出number=42;但是并发错误的话,可能会打印出number=0或者一直循环,无法终止。ready和number都是类变量,在类加载的准备阶段都是初始化成0,在类加载的初始化阶段才被赋值成程序员想要的效果,但是jvm会对指令进行优化重排序,可能先执行ready=true;但在还没有执行number=42时,读线程已经执行完while语句,打印number的值,那肯定是0了。
3. 1.1 失效数据
竞态条件里

1.ifA2.     then B

在执行完语句1,还没有执行语句2时,语句1的状态发生改变,那么A就是一个失效数据了。

3.1.2 加锁与可见性

内置锁可以用于确保某个线程以一种可预测的方式来查看另一个线程的执行结果。
java并发编程实践之对象的共享_第2张图片

线程A,B使用同一把锁,线程A的同步代码块操作先于线程B的同步代码块操作,那么线程A操作的结果在线程B拿到同一把对象锁之后都可以看到,比如,线程B可以看到x=1;


3.1.3 volatile变量

volatile工作原理:每个线程都有一个私有的工作内存,线程可以共享主存,volatile变量被存放在主存里面,如果线程A从内存中读取并修改了volatile变量,那么这个变量要被存储到主存中去,其他线程想要读写该变量都要重新到主存里面去获取该变量。也就是volatile变量不想其他普通变量一样,可以被缓存到线程的私有工作内存里面,每次读写volatile变量,都要重新倒内存中去拿。

volatile变量对可见性的影响比volatile变量本身更加重要。当线程A首先写入一个volatile变量,线程B随后读取该volatile变量,再写入volatile变量之前对线程A可见的所有变量的值,在线程B读取了volatile变量后,对B也是可见的。因此,从内存的角度来看,写入volatile变量相当于撤出同步代码块。

加锁机制既能确保可见性又能确保原子性,但是volatile只能确保可见性。当且仅当满足以下所有条件时,才会使用volatile变量:


  • 当变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程能修改变量。

  • 该变量不会和其他变量一起纳入不变性条件。

  • 该变量没有加锁。

3.2 发布与逸出

发布:对象可以被其他线程和对象使用;
逸出:对象还没有正确创建就被其他线程看见,但对于逸出要防止构造函数中this引用的逸出,比如构造函数中新创建并启动一个线程,那么新线程就会将this引用逸出。构造函数可以创建线程,但start或者initialize不能再构造函数里面。

有个博客写的比较好,附上供大家参考[http://www.cnblogs.com/wufengtinghai/p/5260357.html]


3.3 线程封闭

你可能感兴趣的:(java,java)