(Java)每天进步一点点-------------线程锁

来源:互联网 发布:mac git 忽略ds store 编辑:程序博客网 时间:2024/06/06 05:56

JVM中所有的变量存储在主内存中(即对所有的线程都是共享的),所有实例和实例的字段都在此区域。但每个线程也有自己的工作内存。

(工作内存由缓存和堆栈组成:1.缓存保存的是从主内存同步过来的变量的值)

线程对某个变量的操作步骤: 
1.从主内存中复制数据到工作内存 的缓存中
2.执行代码,对数据进行各种操作和计算 
3.把操作后的变量值重新写回主内存中 

回到这三个步骤,这个顺序是我们希望的,但是,JVM并不保证第1步和第3步会严格按照上述次序立即执行。因为根据java语言规范的规定,线程的工作内存和主存间的数据交换是松耦合的,什么时候需要刷新工作内存或者什么时候更新主存的内容,可以由具体的虚拟机实现自行决定。由于JVM可以对特征代码进行调优,也就改变了某些运行步骤的次序的颠倒,那么每次线程调用变量时是直接取自己的工作存储器中的值还是先从主存储器复制再取是没有保证的,任何一种情况都可能发生。同样的,线程改变变量的值之后,是否马上写回到主存储器上也是不可保证的,也许马上写,也许过一段时间再写。那么,在多线程的应用场景下就会出现问题了,多个线程同时访问同一个代码块,很有可能某个线程已经改变了某变量的值,当然现在的改变仅仅是局限于工作内存中的改变,此时JVM并不能保证将改变后的值立马写到主内存中去,也就意味着有可能其他线程不能立马得到改变后的值,依然在旧的变量上进行各种操作和运算,最终导致不可预料的结果。 

这可如何是好呢?还好有synchronized和volatile: 
1.多个线程共有的字段应该用synchronized或volatile来保护. 
2.synchronized负责线程间的互斥.即同一时候只有一个线程可以执行synchronized中的代码. 
synchronized还有另外一个方面的作用:在线程进入synchronized块之前,会把工作存内存中的所有内容映射到主内存上,然后把工作内存清空再从主存储器上拷贝最新的值。而在线程退出synchronized块时,同样会把工作内存中的值映射到主内存,不过此时并不会清空工作内存。这样一来就可以强制其按照上面的顺序运行,以保证线程在执行完代码块后,工作内存中的值和主内存中的值是一致的,保证了数据的一致性! 
3.volatile负责线程中的变量与主存储区同步.但不负责每个线程之间的同步. 
volatile的含义是:线程在试图读取一个volatile变量时,会从主内存区中读取最新的值。现在很清楚了

0 0
原创粉丝点击