java synchronized
来源:互联网 发布:身份鉴权超时cms 编辑:程序博客网 时间:2024/05/22 13:45
synchronized /
'sɪŋkrənaɪzd/
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
看如下代码 :
class T { public static boolean asleep = false; public static int count = 1 ; public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 4; i++) { new Thread(new Runnable() { @Override public void run() { Test(); } }).start(); } Thread.sleep(3000); asleep = true; System.out.println("end"); } public static void Test( ) { while (!asleep) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Add(); } } public static void Add() { count++; System.out.println("@===i=="+count); } }运行效果如下:
可以发现在多线程下 打印出来的 i++ 并不是依次相加的 为什么会出现这种情况呢 ?这个是由于线程内部变量副本引起的。
当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。如下图:
read and load 从主存复制变量到当前工作内存
use and assign 执行代码,改变共享变量值
store and write 用工作内存数据刷新主存相关内容
其中use and assign 可以多次出现
但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果不会依次相加。
为了防指多线程加载同一count值。只需要在Add()方法前加上 synchronized 就ok了
public synchronized static void Add() { count++; System.out.println("@===i=="+count); }
0 0
- Java synchronized
- Java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- Java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- java synchronized
- Java synchronized
- Java synchronized
- Java synchronized
- java读取hive导出的数据
- HDU 1754 I HATE IT
- oracle jdeveloper 代码智能提示+字体+编码 配置方法
- c#params应用
- 机房收费系统——MDI窗体与子窗体问题
- java synchronized
- Cxf Webservice安全认证
- Java Thread Stop方法以及替换实现
- 完全卸载oracle11g步骤
- Drawable资源(包含shape)
- ios7自带的晃动效果
- 子线程如何获取和设置 或者控制窗口实时显示数据(网上的资料经个人整理拼凑总结)
- 多校联盟--20140801--G - Christmas Play
- Linux自学路线图