• jsr133-第三四章


     3:Informal Semantics

      当代码被重排序的时候,一个程序必须被正确的同步来避免多种类型的违反直觉的行为发生。使用正确的同步不能保证程序里上述的行为是正确的。但是,使用它允许一个程序员以一种简单的途径来推理出一个程序的可能行为;一个正确同步的程序的行为是极少依赖可能的重排序的。没有正确的同步,非常奇怪的、令人迷惑的和匪夷所思的行为就可能会出现。

      有两个关键的办法来理解一个程序是否正确同步了:

      1:Conflicting Accesses (访问冲突)

        两个访问(读取或者写入)同一个共享字段或者数组元素,如果其中至少有一个访问时写入那么就被称为冲突Conficting。

      2:Happens-Before Relationship 

        两个行为可以通过happens-before关系进行排序。如果一个行为happens-before另一个行为,那么第一个操作是可见的并且顺序先于第二个操作。应该被强调的事,一个两个操作之间的happens-before关系,并不意味着这些行为在java平台的实现中一定按照这样的顺序发生。happens-before关系通常强调的是两个互相冲突的行为之间的顺序,并且定义设么时候数据竞争将会发生。有一下一些途径来引入happens-before排序,包括:

      *  一个线程中的每一个行为happens-before 当前线程中的后续一切操作

      *  一个monitor上的解锁操作happens-before 同一个monitor上的后续一切锁定操作

      *  一个volatile类型的field的写操作happens-before 这个volatile类型的field的任何后续读操作

        * 一个线程的start()方法的调用happens-before 这个启动了的线程的任何其他动作

        * 一个线程的所有操作happens-before 任何其他线程在这个线程上调用join()的成功返回(其实就是说 任何其他线程调用对这个线程的join()方法,那么必须等到这个线程的所有动作全部执行完成,之后才能继续join()之后的代码)

        * 如果操作a happens-before 操作b,并且b happens-before 操作c,那么操作a happens-before 操作c

      在第五章,有针对Happens-beofre的更详细的讲解。

      当一个程序包含两个互相竞争的访问,并且并没有按照happens-before关系进行排序,那么这就叫做包含一个数据竞争(a data race)。一个正确的同步程序是没有数据竞争的。(3.1章节包含一个微妙的也是重要的说明)。

      图3展示了一个更加精细微秒的同步代码,展示了同一个程序里的两次不同的执行,对于两个共享变量X和Y的冲突访问。程序里两个线程锁定和解锁着一个监视器monitor M1。在图3a展示的执行里,在两个共享变量的访问上都执行了happens-before顺序。然而,在图3b展示的执行里,对于共享变量X的访问,并没有按照happens-before 顺序执行,因此我们说这个程序并不是正确同步的。

      一个程序如果是正确同步的,那么这个程序的所有执行都会表现出正确的顺序一致性。这是对于一个程序员的极其强烈的保证。一旦程序确定了代码中没有数据竞争,那么就不需要担心程序重排序对他们造成影响。

      3.1 Sequential Consistency

      Sequential Consistency 顺序一致性是一个非常强有力的保证来确保程序执行的可见性和顺序性。有了顺序一致行的执行,就有了所有单独操作的整体运行顺序是与程序运行的顺序一致的。

      每一个单独的操作都是原子的并且可以被每一个线程直接访问。如果一个程序没有数据竞争,那么这个程序的所有执行都将是顺序一致的。正如前边提到的那样,当一些操作本应该是原子的但却没有得到保障的情况下,顺序一致性或者以及数据竞争的自由仍然会发生一些错误。

      如果我们使用顺序一致性作为我们的内存模型,那么我们之前讨论过的很多编译器的以及处理器的优化都将会变为非法的。例如,在图2中,一旦3写入p.x发生,随后的读操作就需要看到这个值。

      已经讨论了顺序一致性,我们可以使用它来提供一个重要的说明关于数据竞争以及正确的同步代码。一个数据竞争发生在一个有数据竞争的操作但没有正确同步顺序的程序执行里。一个程序要正确同步,当且仅当所有的顺序执行的操作都没有数据竞争。那样的话,就只需要推出顺序执行的操作来决定代码是否正确同步。

      对于非final类型的属性,一个完整的内存问题处理在第4-6章。

      3.2 Final Fields (Final属性)

      被声明为final的属性只初始化一次,正常情况下永远不会被改变。对于final类型的详细语义多少跟普通属性有一些区别。事实上,编译器有大量的自由来穿过同步障碍读取final属性,并且调用任意的或者未知的方法。相对的,编译器被允许保持final属性缓存在寄存器里,并且在正常属性已经被从内存中重新加载的地方,final属性不会被重新加载。

      Final域也被程序员用来实现线程安全的不可变对象在syn-chronization之外。一个线程安全的对象应该是对所有线程都是不可变的,即使一个数据竞争在线程之间通过不可变对象的引用来传递。这样可以提供安全的保障来避免不可变的类被错误的或者恶意的代码滥用。

      Final域提供的不变性保障必须被正确应用。当一个对象的构造方法结束后,就认为这个对象已经初始化完成了。

      

       

  • 相关阅读:
    JQuery学习笔记(1)——选择器
    Web前端——表单提交和Js添加选项
    Web前端——JavaScript练习
    Web前端——css
    Web前端——JavaScript笔记
    sirius的学习笔记(2)
    sirius的python学习笔记(1)
    Get和Post的请求
    IIS的配置
    一般处理程序aspx
  • 原文地址:https://www.cnblogs.com/aquariusm/p/6308514.html
Copyright © 2020-2023  润新知