开发者社区> 问答> 正文

java Synchronized 内存可见性问题:报错

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;
		}
	}
}



假设有3个线程,线程1先调用set方法,然后线程2调用get方法,线程3调用get2方法

则可以肯定线程2可以看到线程1修改的num值,

线程3是否肯定可以看到最新值呢?



展开
收起
kun坤 2020-06-07 12:19:52 558 0
1 条回答
写回答
取消 提交回答
  • 线程3可以看到最新值,java会对锁住的对象判断是否处于竞争中,如果没有被竞争,那么会立即执行。如果三个线程是并发执行,那种情况就不确定了,线程2都不一定是最新值,因为有可能线程1还未执行。

    如果线程1先执行,那么lock1就已经被释放了,那么此时lock1和lock2就都是处于未被锁住的情况,即不存在锁竞争关系,线程2 、3同时执行必然能取到最新值,不然java的多线程会出现不可预估的数据错误,后果很严重。

    锁的意义是防止线程竞争造成共享数据混乱,有竞争就会让线程排队等候,其实就是把同时执行的情况改造成类似同步的顺序执行,Synchronized这个词的意思就是“同步”,其本质就是让线程的异步变为同步

    ######回复 @疯狂的骑士 : 是锁未处于竞争状态其内的共享变量应该是最新的######按你的说法, synchronized代码块内,所有的共享变量都是最新值,不管是不是同一个锁,synchronized的语义可以理解为刷新主存的变量值到当前线程的缓存中? 最近的项目涉及这个问题,我加了synchronized,但是变量值没更新,找不到哪出错了,后面把变量声明为volatile,才解决问题。######

    描述里只是说明synchronized开始时刷新一次和退出时提交一次,但并不表示代码块在执行的过程中,不会提交或刷新共享变量,所以情况分很多种,纠结这种问题没什么意义.

    你可以在set()方法里写一个循环对num进行累加,在get2()里多次获取,看看锁未释放时,num是不是不变的.

    ######这个问题可是很重要的,而且这种问题很难测试
    2020-06-07 12:19:58
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载