前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中Volatile和Synchronized关键字的区别

Java中Volatile和Synchronized关键字的区别

作者头像
程序你好
发布2018-09-29 11:04:37
8380
发布2018-09-29 11:04:37
举报
文章被收录于专栏:程序你好程序你好

本文介绍了Java中的一些基本概念,但非常重要。

volatile是一个字段修饰符,而synchronized修饰了代码块和方法。

因此,我们可以使用这两个关键字指定一个简单访问器的三个变量:

代码语言:javascript
复制
        int i1;                      
        int geti1() {return i1;}
        
        volatile int i2;              
        int geti2() {return i2;}        
        
        int i3;
        synchronized int geti3() {return i3;}

在上面,我们定义了三个整数变量:i1、i2和i3。我们定义了三个相应的getter方法:geti1()、geti2()和geti3()。

geti1()访问当前线程中存储在i1中的值。

线程可以拥有变量的本地副本,并且数据不必与其他线程中的数据相同。特别是,另一个线程可能在其线程中更新了i1,但是当前线程中的值可能与更新后的值不同。实际上,Java演示了“主”内存的概念,这是存储变量当前“正确”值的内存。线程可以有自己的变量数据副本,线程副本可以不同于“主”内存。

因此,如果thread1和thread2都更新了i1,那么“主”内存的值可能为1,thread1的值为2,thread3的值为3。但是,更新的值还没有传播到“主”内存或其他线程。

另一方面,geti2()有效地从“主”内存访问i2的值。不允许volatile变量具有与当前保存在“主”内存中的值不同的变量的本地副本。实际上,声明为volatile的变量必须在所有线程之间同步它的数据,以便在任何线程中访问或更新变量时,所有其他线程都能立即看到相同的值。通常,volatile变量比普通变量有更高的访问和更新开销。通常,线程被允许拥有自己的数据副本,这是为了提高效率。

volatile和synchronized有两个区别:

首先,synchronized在monitors(监视器)上获得并释放锁,它一次只能强制一个线程执行代码块。这是同步的一个非常著名的方面。但是synchronized也同步了内存。实际上,synchronized使整个线程内存与“主”内存同步。

因此,执行geti3()会执行以下操作:

1、线程为这个对象获取监视器上的锁。

2、线程内存刷新所有的变量,也就是说,它的所有变量都有效地从“主”内存读取。

3、执行代码块。在本例中,这意味着将返回值设置为i3的当前值,i3可能刚刚从“主”内存中重置。

4、对变量的任何更改通常会被写到“主”内存中,但是对于geti3(),我们没有更改。

5、线程释放这个对象在监视器上的锁。

因此,当volatile只在线程内存和“主”内存之间同步一个变量的值时,同步将同步线程内存和“主”内存之间的所有变量的值并锁定,并释放一个监视器来控制多线程之间的所有权。

从这些信息可以得出结论,synchronized比volatile的开销更大。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序你好 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档