java中的Synchronized有2个作用
1. 互斥访问
2. 保证内存可见性
关于第二点,总是有点疑惑,看了很多资料,一般这么描述,
1. 在同一个锁上修改,读取共享变量,读线程总是可以获取最新变量值。
2. 后面又有 这样的描述: 线程释放锁时会将强制刷新工作内存中的脏数据到主内存中,获取一个锁将强制线程装载(或重新装载)字段的值.
这里有个链接 http://ifeve.com/syn-jmm-visibility/
这样我也有点困惑,以前没仔细想清楚,特地写了以下代码,希望高手可以解惑。
class Test{ static Object lock1 = new Object(); static Object lock2 = new Object(); static int num = 0; static void set(int a){ synchronized (lock1) { num = a; } } static int get(){ synchronized (lock1) { return num; } } static int get2(){ synchronized (lock2) { return num; } } }
则可以肯定线程2可以看到线程1修改的num值,
线程3是否肯定可以看到最新值呢?
线程3可以看到最新值,java会对锁住的对象判断是否处于竞争中,如果没有被竞争,那么会立即执行。如果三个线程是并发执行,那种情况就不确定了,线程2都不一定是最新值,因为有可能线程1还未执行。
如果线程1先执行,那么lock1就已经被释放了,那么此时lock1和lock2就都是处于未被锁住的情况,即不存在锁竞争关系,线程2 、3同时执行必然能取到最新值,不然java的多线程会出现不可预估的数据错误,后果很严重。
锁的意义是防止线程竞争造成共享数据混乱,有竞争就会让线程排队等候,其实就是把同时执行的情况改造成类似同步的顺序执行,Synchronized这个词的意思就是“同步”,其本质就是让线程的异步变为同步
描述里只是说明synchronized开始时刷新一次和退出时提交一次,但并不表示代码块在执行的过程中,不会提交或刷新共享变量,所以情况分很多种,纠结这种问题没什么意义.
你可以在set()方法里写一个循环对num进行累加,在get2()里多次获取,看看锁未释放时,num是不是不变的.
######这个问题可是很重要的,而且这种问题很难测试版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。