《Java Concurrency in Practice》之Volatile variables

        Java语言还提供了另一种较弱形式的同步选择,即volatile变量,以确保更新的变量是可预见的传播到另一个线程。

        当一个成员变量(field)被声明用volatile修饰时,编译器(the compiler)和运行时(runtime)都会注意到该变量是共享的,并且不会将该变量的操作与其它内存操作重新排序。

        volatile变量不会被缓存在寄存器或者对其它处理器不可见的地方,因此在读取volatile修饰的变量时总会返回最新写入的值。

        当访问volatile变量时不会执行加锁操作,这样就不会引起正在执行的线程阻塞,从而使得volatile变量是一种比synchronized关键字更轻量级的同步机制。

        volatile变量对可见性的影响超出了volatile变量本身的价值。当线程A首先写入一个volatile变量,并且线程B随后读取该变量时,在写入volatile变量之前对线程A可见的所有变量的值,在线程B读取了volatile变量后,对线程B也是可见的。因此,从内存可见性的角度来看,写入volatile变量相当于退出同步代码块,而读取volatile变量就相当于进入同步代码块。可是,并不建议过度依赖volatile变量提供的可见性。如果在代码中依赖volatile变量来控制状态的可见性,通常比使用锁的代码更脆弱,也更难以理解。

        仅当volatile变量能简化代码的实现,及验证你的同步策略时,才使用volatile变量。当验证正确性时需要对可见性进行复杂的判断(subtle reasoning),这种情况不要使用volatile变量。有效使用volatile变量的方式,包括确保自身状态的可见性,确保引用对象的可见性,或表明一个重要的生命周期事件(such as initialization or shutdown)的发生。

        volatile变量的一种典型用法:检查某个状态标记以判断是否退出循环。如下代码示例,数绵羊。

    volatile boolean asleep;
    ..
        while (!asleep) 
            countSomeSheep();
        volatile的局限性:加锁机制既可以确保可见性,又可以确保原子性;volatile变量只能确保可见性。

        当且仅当满足以下所有条件时,才应该使用volatile变量:

  • 对变量的写入操作不依赖变量当前的值,或者能确保只有单个线程更新变量的值。(Writes to the variable do not depend on its current value, or you can ensure
  • 该变量不会与其它状态的变量,一起纳入到不变性条件中。(The variable does not participate in invariants with other state variables;)
  • 当访问变量时,不需要任何加锁的理由。(Locking is not required for any other reason while the variable is being accessed.)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值