线程安全问题与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标记的变量可以被编译器优化

转载于:https://www.cnblogs.com/x54256/p/8733980.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值