【JAVA】volatile和synchronized的区别

news/2024/5/17 16:39:45 标签: volatile, synchronized, 线程

共性:

volatilesynchronized都用于保证多线程中数据的安全

区别:

(1)volatile修饰的变量,jvm每次都从主存(主内存)中读取,而不会从寄存器(工作内存)中读取。

synchronized则是锁住当前变量,同一时刻只有一个线程能够访问当前变量

(2)volatile仅能用在变量级别,而synchronized可用在变量和方法中

(3)volatie仅能实现变量的修改可见性,无法保证变量操作的原子性。而synchronized可以实现变量的修改可见性与原子性


【1】可见性

说的是一个线程如果更改了某个变量的值,其他线程能够立刻知道这个变量更改后的值

【2】原子性

一个操作要么全做,要么全不做,就像不可分割的原子一样。银行转账这个操作必须具有原子性,A转账给B1000元,A账户减去1000元,B账户加上1000元,两个操作不可分割,不可单独出现,否则会出现意料之外的结果。


例:volatile int  i=0;并且大量线程调用i的自增操作,那么volatile可以保证变量的安全吗?

不可以保证,volatile不能保证变量操作的原子性,自增操作包括三个步骤,分别是读取,加一,写入,由于这三个子操作的原子性不能被保证,那么n个线程总共调用n次i++的操作后,最后的i的值并不是大家想的n,而是一个比n小的数

解释:比如A线程执行自增操作,刚读取到i的初始值0,然后就被阻塞了

B线程现在开始执行,还是读取到i的初始值0,执行自增操作,此时i的值为1

然后A线程阻塞结束,对刚才拿到的0执行加一与写入操作,执行成功后,i的值被写成1了,

我们预期输出2,可是输出的是1,输出比预期小。

代码验证

package day0807;

import java.util.ArrayList;
import java.util.List;

public class VolatileTest {
    public volatile int i = 0;

    public void increase() {
        i++;
    }

    public static void main(String args[]) throws InterruptedException {
        List<Thread> threadList = new ArrayList<>();
        VolatileTest test = new VolatileTest();
        for (int j = 0; j < 10000; j++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    test.increase();
                }
            });
            thread.start();
            threadList.add(thread);
        }

        //等待所有线程执行完毕
        for (Thread thread : threadList) {
            thread.join();
        }
        System.out.print(test.i);
    }
}

输出为

(4)volatile不需要加锁,因此不会造成线程的阻塞,而且比synchronized更轻量级,而synchronized可能导致线程的阻塞


http://www.niftyadmin.cn/n/1705771.html

相关文章

C++带参数默认值的函数

定义形式&#xff1a; void fun(int a 1 ,int b 2 ,int c 3 ,int d 4){ //函数定义cout<<"a"<<a<<endl;cout<<"b"<<b<<endl;cout<<"c"<<c<<endl;cout<<"d"<<d…

【JAVA】Object类的方法简谈

Object类的方法简谈 Java中所有的类都继承自Object类&#xff0c;那我们今天来探讨一下Object类中的方法 PS:Object源码中&#xff0c;作者那一栏中&#xff0c;出现了这个 package java.lang;/*** Class {code Object} is the root of the class hierarchy.* Every class h…

使用widnows精灵

//你可以从下面的地址下载精灵//http://www.microsoft.com/msagent/downloads.htm//privateAxAgentObjects.AxAgent axAgent1; axAgent1.Characters.Load("Genie","Genie.acs");//导入精灵吉尼&#xff08;Genie&#xff09;AgentObjects.IAgen…

ASP.NET MVC应用程序展示RDLC报表

学习ASP.NET MVC这样久&#xff0c;在学习&#xff0c;练习与应用过程中&#xff0c;觉得很多知识与以前的ASP.NET多有区别&#xff0c;但是实现操作起来&#xff0c;细处又有许多相近的地方。 本篇跟大家一起学习RDLC报表&#xff0c;是在ASP.NET MVC应用程序中实现。在实现过…

【Spring】@Resource、@Autowired和@Qualifer三者的区别

Resource、Autowired和Qualifer三者的区别 Spring中以上三个注解可以用来实现依赖注入&#xff0c;但在使用时知道三者的区别与联系是比较重要的 Resource使用注意事项 例&#xff1a; Resource CityDao citydao; 【1】 则首先根据类名&#xff0c;将类名首字母小写得到ci…

Sicily 1814. 日期计算问题

【转自网络大神&#xff0c;由本人整理】 Description试用 C的类来表示日期,给定 2 个日期 yyyy.mm.dd 求两个日期间相差的天数。 Input第 1 行为一个正整数T&#xff0c;表示测试数。 对于每个测试点&#xff0c;第 1 行与第 2 行分别有两个日期 yyyy.mm.dd。 Output对于每个测…

hadoop安装遇到的各种异常及解决办法

hadoop安装遇到的各种异常及解决办法 异常一: 2014-03-13 11:10:23,665 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: Linux-hadoop-38/10.10.208.38:9000. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries10,…

listener无故down掉,重启失败

9月9日上午收到vip数据库报警&#xff0c;提示DBalert vipdb connect error&#xff1a;ORA-12564:TNS:connection refused。上去后发现监听down掉&#xff0c;但是正常启动却起不来&#xff0c;提示如下&#xff1a;LSNRCTL> startStarting /home/oravip/product/92/bin/tn…