volatile关键字实现轻量级同步机制/统计1秒内可以进行多少次加操作

可见性:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
原子性:即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
有序性:即程序执行的顺序按照代码的先后顺序执行
参考:
缓存一致性协议:
https://blog.csdn.net/zhuzongwei1988/article/details/5531158
总线锁机制:
https://blog.csdn.net/qq_35642036/article/details/82801708

一、Volatile关键字→轻量级同步机制

1. 特点:
Volatile不能提供原子性

  • 内存可见性:对于线程共享变量,一个线程的修改,另一个线程可以直接获取修改后的值(加了volatile关键字,主线程修改标志位时,子线程可以立即看到)
  • 防止指令的重排序(有序性)

2.作用:

  • 写过程
    1. 将修改后的内容写到cache(工作内存)中,当前变量是volatile修饰的变量则会立即写回主内存
    2. 其他线程的工作内存上监测总线(一致性协议)上的变量有被修改过,则将当前工作内存的变量置为无效

  • 读过程
    其他线程在读取时,先在自己的工作内存中判断当前的变量是否有效,有效(未修改)则读取, 无效(其他线程对变量做了修改)则直接从主内存中读取最新修改后的值

3.实现轻量级同步的详细步骤:
当前有两个线程,thread1和thread2
thread1执行 a+=1
thread2执行 a+=1
将a=1从主内存备份到线程1的私有内存,检测是否有volatile修饰,在私有内存中若对副本进行修改,则立即将主内存里的值回写
(回写步骤:

  • 内容回写(直接修改当前值为最新的)
  • 一种机制:线程2在总线上自动监听,如果线程2的私有内存有未回写之前的值,则将其置为无效)

总线分为:地址总线,数据总线,消息总线

4.什么时候使用Volatile
Volatile关键字为实例域的同步访问提供了一种免锁机制。如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。
例如:
有一个布尔类型的性别,它的值被一个线程设置,却被另一个线程查询,这样可以用synchronize锁来实现,但是如果一个线程已经给对象加了锁,isSex和setSex两个方法可能会发生阻塞。这种情况我们就可以使用volatile变量来声明sex,就可以不用synchronize关键词,避免阻塞。

  • synchronized,会产生阻塞
 private boolean sex;
    public synchronized boolean isSex(){
        return sex;
    }
    public synchronized void setSex(){
        sex = true;
    }
  • volatile 不会阻塞
 private volatile boolean sex;
    public boolean isSex(){
        return sex;
    }
    public  void setSex(){
        sex = true;
    }

二、统计一秒内可以进行多少次加操作

/**
 * @auther: 巨未
 * @DATE: 2019/4/9 0009 20:59
 * @Description:
 *
 * 统计一秒进行多少次++操作
 */
public class VolatileDemo {

    static volatile boolean flag = false;
    public static void main(String[] args) {
        System.out.println("主线程开始...");
        new SubThread().start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("主线程结束");
    }

    static class SubThread extends Thread{
        @Override
        public void run() {
            System.out.println("子线程开始执行...");
            int i = 0;
            while (!flag){
                i++;
            }
            System.out.println("子线程结束>"+i);
        }
    }
}

执行结果:
在这里插入图片描述
通过对代码分析研究
在.java编程生成的.class文件看出,
字节码文件中,加了volatile修饰的变量会在flag处加:Acc_VOLATILES;
在底层汇编语言上就是给该变量前添加!#LOCK前缀

参考:《Java核心技术 卷1 》第14章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值