java中的广东快乐十分平台开发变量详解

广东快乐十分平台开发Q1446595067
变量是java语言提供的一种稍弱的同步机制,他可以用来确保将变量的更新操作通知到其他的线程。当我们把一个变量声明为Volatile类型后,编译器运行时会注意到这个变量是共享变量,因此不会讲该变量上的操作与其他内存操作后一起重排序。此变量也就不会被缓存在寄存器上或者对其他处理器不可见的地方,所以在读取volatile变量时总会返回最新写入的值。

以下面的例子为主:

使用sychronied关键字进行同步的时候:可以这样写:

public class SychronizedNumber {

    // @GuardedBy("this")(对象中的内部锁,包括方法和域是这个对象的一个成员)
    @GuardedBy("this")
    private int value;

    public synchronized int get(){ return value; }

    public synchronized void set(int value) { this.value = value; }
}

理解volatile变量的一种有效方法是:将他们的行为想象成上边程序SychronizedNumber 的类似行为,并将volatile变量的读操作和写操作分别替换为get方法和set方法。然而,在访问volatile变量时不会加锁,因此也就不会使执行的线程堵塞,因此volatile变量时一种比synchronized关键字更轻量级的同步机制(在当前的大多数处理器架构上,读取volatile变量的开销之比读取非volatile变量的开销略高一些)

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

紧当volatile变量能简化代码的实现以及时对同步策略的验证时,才应该使用它们。如果在验证正确性时需要对

可见的行进行复杂的判断,那么就不要使用volatile变量。volatile变量的正确使用方式包括:确保它们自身状

态的可见性,确保它们所引用对象的状态的可见性,以及标识一些重要的程序生命周期事件的发生(例如,初始化或关闭)

另外下面的程序给出了volatile变量的一种典型用法:检查某个状态标记以判断是否退出循环。在下面的示例中,线程师徒通过类似于绵羊的传统方法进入休眠状态。为了使这个示例能够正确的执行,asleep必须为volatile变量。否则,当asleep被另一个进程修改时,执行判断的线程缺发现不了。我们也可以用锁确保asleep更新操作的可见性,但这将时代码变得复杂。

volatile boolean asleep;
        while(!asleep)
            countSomeSheep();

虽然volatile变量很方便,但是也存在一定的局限性。此volatile变量通常用某个操作完成,发生中断或者状态的标志,例如上面程序中的asleep标志。尽管volatile变量也可以用于表示其他的状态信息,但在使用中还是应该小心。例如,volatile的的语义不足以确保递增操作(count++)的原子性,除非你能确保只有 一个线程对变量执行写操作。(原子变量提供了“读-改-写”的原子操作,并且常常用一个“更好的volatile变量”,后续会讲到)

加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性

当且紧当满足一下条件时,才可以使用volatile变量:

1、对变量的写入操作不依赖变量当前的值,或者能确保只能单个线程更新变量的值。

2、该变量不会与其他状态变量一起纳入不变性条件中。

3、在访问变量时不需要加锁。

扫描二维码关注公众号,回复: 2317748 查看本文章

猜你喜欢

转载自blog.51cto.com/13882835/2148854