Java中Volatile和Synchronized关键字的区别

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

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

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

        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的开销更大。

原文发布于微信公众号 - 程序你好(codinghello)

原文发表时间:2018-08-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

Python模块知识8:configparser、压缩模块

一、configparser模块 configparser用于处理特定格式的文件,其本质上是利用open来操作文件。 文件格式如: ? 1.基本的读取配置文件 ...

1916
来自专栏Python中文社区

每天一个Linux命令:grep

grep 简介 grep (global search regular expression(RE) and print out the line,全面搜索正则...

1975
来自专栏Rgc

scrapy回调函数传递参数

scrapy.Request 的callback传参的两种方式 1.使用 lambda方式传递参数 def parse(self, response): ...

2813
来自专栏Petrichor的专栏

aptitude指令

aptitude update #更新可用的包列表 aptitude upgrade #升级可用的包 aptitude dist-upgrad...

1583
来自专栏小二的折腾日记

day5(面向对象2)

wait notify notifyAll 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,以为只有同步才具有锁。 为什么这些操作线程...

571
来自专栏小樱的经验随笔

【python进阶】深入理解系统进程2

2714
来自专栏Java架构

Java多线程编程——锁优化

1814
来自专栏令仔很忙

Hibernate从入门到放弃(三)----持久化对象

当对象刚创建,和Session没有发生任何关系时,当程序运行完成就立刻消失,被称为瞬时态。瞬态对象不会被持久化到数据库中,也不会被赋予持久化标识,如果程序中失...

1251
来自专栏腾讯移动品质中心TMQ的专栏

从Java乱码谈起

在实际项目开发中,特别是涉及到中文输入输出的时候,大家肯定都被各种乱码问题坑过。如果遇到复杂的系统,为了乱码问题折腾几天也不是不可能。

4846
来自专栏大内老A

ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

在《管道是如何处理HTTP请求的?》中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管...

1926

扫码关注云+社区

领取腾讯云代金券