zoukankan      html  css  js  c++  java
  • 线程安全问题与volatile字段

    线程安全问题

    /**
     * 出现有些没加入list的原因:线程一拿走了这个list当时里面有10个数据,添加一个变成11个
     * 线程二同时拿走了这个list,当时里面有10个数据,添加一个变成11个(但是正常应该是12个,也就是线程1添加的那个数据没有了)
     */
    public class Ticket implements Runnable{
        
        private List<String> list = new ArrayList<>();
    
        public void run(){
            for(int i=0;i<300;i++){
                try {
                    // 调用Thread类的sleep方法,休眠50ms,由于父接口没有throws异常,so我们只能用try...catch
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                list.add("xxx,");
                System.out.println(list.size());
            }
        }
    
    }

    结论:多线程操作同一个全局变量,加上线程锁吧

    volatile字段

    volatile字段的作用:往常线程都是将某个变量复制一份到自己的线程中,经过volatile字段修饰后,就统一的从内存中读取

    原理:volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;

    Volatile 变量具有 synchronized 的可见性特性,但是不具备原子性。这就是说线程能够自动发现 volatile 变量的最新值。

    •  volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由(读取-修改-写入)操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。

    用处:如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。

    两个字段的区别

    1. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住
    2. volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
    3. volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
    4. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
    5. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
  • 相关阅读:
    用 Flask 来写个轻博客
    Django 博客开发教程目录索引
    动态规划问题
    Java课程目录
    React&Vue
    Node.js
    Chrome Input框老是有输入记录的终极解决方案
    php中&运算符的理解与使用
    服务器压测、并发数、配置与资源消耗的关系研究
    定时任务被执行两遍,如何处理?
  • 原文地址:https://www.cnblogs.com/x54256/p/8733980.html
Copyright © 2011-2022 走看看