先行发生原则(Happens-Before)是Java内存模型定义的一个等效判断原则。 依赖这个原则,我们可以通过几条简单规则判断数据是否存在竞争,线程是否安全,而不需要陷入Java内存模型苦涩难懂的定义之中。---“先行发生”原则指的是什么。 下面是Java内存模型下一些“天然的”先行发生关系,这些先行发生关系无须任何同步器协助就已经存在,可以在编码中直接使用。 Java 语言无须任何同步手段保障就能成立的先行发生规则有且只有上面这些。---“时间上的先后顺序”与“先行发生”之间有什么不同?一个操作“时间上的先发生”不代表这个操作会是 “先行发生”。 时间先后顺序与先行发生原则之间基本没有因果关系,所以我们衡量并发安全问题的时候不要受时间顺序的干扰,一切必须以先行发生原则为准。
“先行发生”(happens-before)的原则。 一、什么是先行发生原则 现在就来看看“先行发生”原则指的是什么。 “j=i”,那么可以确定在线程B的操作执行后,变量j的值一定等于1,得出这个结论的依据有两个:一是根据先行发生原则,“i=1”的结果可以被观察到;二是线程C还没“登场”,线程A操作结束之后没有其他线程会修改变量 ,根据程序次序规则,“int i=1”的操作先行发生于“int j=2”,但是“int j=2”的代码完全可能先被处理器执行,这并不影响先行发生原则的正确性,因为我们在这条线程之中没有办法感知到这点。 上面两个例子综合起来证明了一个结论:时间先后顺序与先行发生原则之间基本没有太大的关系,所以我们衡量并发安全问题的时候不要受到时间顺序的干扰,一切必须以先行发生原则为准。
先行发生”原则。 先行发生是Java内存模型中定义的两项操作数之间的偏序关系,如果说操作A先行发生于操作B,就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等 线程启动规则 :Thread对象的start方法先行发生于此线程的每个动作; 线程终止规则 :线程中的所有操作都先行发生于对此线程的终止检测; 线程中断规则 :对线程的interrupt()方法的调用先行发生于被中断线程的代码检测到中断时间的发生 ; 对象终结规则 :一个对象的初始化完成先行发生于它的finalize方法的开始; 传递性 :如果操作A先行发生于操作B,操作B先行发生于操作C,那么,操作A也就先行发生于操作C。 依次分析一下先行发生原则中的各个原则:由于两个方法分别在不同的线程中被调用,程序次序原则不适用;没有同步块,自然不会发生lock和unlock操作,管程锁定原则不适用;value变量没有被volatile
)原则 这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依赖。 先行发生原则 指的是JMM中定义的两项操作之间的依序关系 happens- before关系 主要用于强调两个有冲突的动作之间的顺序,以及定义数据争用的发生时机 如果说操作A先行发生于操作B,就是在说发生 线程中断规则(Thread Interruption Rule) 对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted() A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论 一个操作”时间上的先发生“不代表这个操作会是”先行发生“,那如果一个操作”先行发生“是否就能推导出这个操作必定是”时间上的先发生 也是不成立的,一个典型的例子就是指令重排序 所以时间上的先后顺序与先行发生原则之间基本没有什么关系,所以衡量并发安全问题一切必须以先行发生原则为准。
文章目录 一、指令重排序规范 二、happens-before 先行发生原则 一、指令重排序规范 ---- 指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ; 规范 : 先行发生原则 ; 二、happens-before 先行发生原则 ---- happens-before 先行发生原则 : A happens-before B , A 先于 B 发生 , 使用 指令重排 ; happens-before 先行发生原则 适用场景 : 在以下场景中 , 不进行指令重排 , 这些先后顺序 , 绝对不能被打乱 , 否则会出现严重线程安全问题 ; 程序次序原则 检测到 中断时 事件的发生 ; 必须先发生中断 , 然后才能被检测到 ; 不能还没发生中断 , 就可以检测到中断发生 ; 对象终结 : 对象的创建 先于 对象的终结 , 创建就是调用构造函数 , 终结就是调用 finalize 方法 ; 只要符合上述规则 , 不需要进行同步 , 就可以成立 ; 通过 " happens-before 先行发生原则 " 可以判定两个线程的操作 , 是否有发生冲突的可能 ;
2010年的全球移动通信大会上,谷歌时任首席执行官Eric Schmidt 提出:产品设计应遵循 “移动先行” 的原则。 该原则具体指什么?遵循该原则的依据有哪些?为什么它在产品设计中如此重要? 一、什么是“移动先行” 原则? 为了更好地理解该原则,首先要了解两个概念: 1. 响应式网页设计(RWD) 一种网页设计方法。 因为“移动先行”原则,就是“逐步增强” 策略的一个具体表现形式。 “移动先行”,顾名思义,即在设计多终端产品时,首先设计限制较多的移动端版本,再一步步向高级终端迈进。 ? 二、为什么在产品设计中,“移动先行”的原则如此重要? 除了以上提到的“逐步增强”的设计策略的可操作性更强外,“移动先行”原则其实还具有强大的现实基础:移动端需求的爆炸式增长。 移动端需求的爆炸式增长,要求设计师在进行产品设计时,重视产品的移动端版本,遵从 “移动先行” 的设计原则。 三、如何在产品设计中践行移动先行原则?
先行发生原则 如果JMM中所有的有序性都只靠volatile和synchronized,那么有一些操作将会变得很繁琐,但我们在编写Java并发代码时并没有感到这一点,这是因为Java语言中有一个先行发生 先行发生原则是指JMM中定义的两项操作之间的依序关系 如果说操作A先行发生于操作B,就是在说发生B前,A产生的影响能被B观察到,“影响”包含了修改内存中共享变量的值、发送了消息、调用了方法等。 传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。 一个操作”时间上的先发生“不代表这个操作会是”先行发生“,那 如果一个操作”先行发生“是否就能推导出这个操作必定是”时间上的先发生“呢?也是不成立的,一个典型的例子就是指令重排序。 所以时间上的先后顺序与先生发生原则之间基本没有什么关系,所以衡量并发安全问题一切必须以先行发生原则为准。
现存的原则会发生改变,新的原则会被加进来,旧的原则将不再适用。实践和从实践中获得的经验,促使我们发展了那些原则。 与原则185和201 (强调软件部署后,需求可能发生巨大变化)不同,本原则想表达,在开发过程中,软件也可能发生巨大变化。这些变化可能体现在编写新的代码、新的测试计划或新的需求规格说明上。 原则21 不同的阶段,使用不同的语言 业界对“用简单方法解决复杂问题”的永恒渴望(见原则19),促使许多人宣称:最佳的软件开发方法,是在整个开发生命周期中使用相同的符号表达方法。 原则162强调需要预先分析所有潜的难,提前制订应急计划,并不断重新评估新的风险。本原则强调需要预想这些风险成为现实。最大的管理灾难会在你认为不会发生的时候出现。 为了避免这种情况的发生,要确保你正在做的变更是经过核准的(见原则182及183),对每项变更进行核查(见原则97),并在每组变更后进行回归测试(见原则196)。
在二十世纪五十年代就存在深度学习的概念了。麦肯锡全球研究院发文简要回顾了深度学习是如何从概念发展为现实的,而使之实现的关键人物又是谁。 后来,美国麻省理工学院(MIT)的马文·明斯基(Marvin Minsky)和西摩·帕普特(SeymourPapert)在其1969年出版的书《感知器》中,用数学的方法展示了感知器只能进行很基础的任务, 他们的书还讨论了训练多层神经网络的难点。 2012年,辛顿和他的学生在著名的 ImageNet 竞赛中取得了突出的结果,彰显了深度学习的强大。该竞赛以李飞飞等人整理的数据集为基础。 深度学习也增强了强化学习这一已存在的领域,理查德·萨顿(Richard Sutton)就是其中一位顶尖的研究人员,他牵头让谷歌DeepMind开发的系统取得了多次棋类比赛的胜利。
Open-Closed Principle,"开闭原则"百科上是这么说的:一个软件实体(如类、模块、函数)应该对扩展开放,对修改关闭。 为什么? 开闭原则是面向对象设计原则中最基础的原则,可称之为原则的原则,也可以说是原则的指导思想,它强调的是既稳定又灵活,在不修改源代码的情况下又增加了新功能,核心思想是面向抽象编程。 "开闭原则是抽象类,其他五大原则是具体的实现类。"对测试的影响,可以提高复用性,提高可维护性,面向对象开发的要求。 怎么用? (来说说抽象,抽象是对一组事物的通用描述,它没有具体的实现,也就表示它有很多的可能性,在程序语言中抽象表现为在接口或抽象类定义一些可变的行为,并且能够实现对扩展开放,其包含三层含义: 第一,通过接口或抽象类约束扩展 最后再说说封装变化,包含两层含义: 将相同的变化封装到一个接口或抽象类中; 将不同的变化封装到不同的接口或抽象类中;
今天在群里有个同学问,说他给github上的一个项目写了个插件,然后对方说他的插件的空格缩进不对,他就想问问几个空格缩进才对? 先说下我的观点,我是4个空格,并且我直接就是tab键排齐就完事了。 另外JS本身也确实没有一个真正官方的代码风格指南,没有官方文档,然后各个社区也没有共识。 但真要是用2个空格来缩进,这代码确实有点难看,看这个angular.js,这个网上找来的看看 ? 这事也分二面说,如果你是给别人写插件,那相当于你加入别人的项目,自然要按着别人的规矩来。别人是4空格,你写的JS就必须是4空格。。 所以这事说到最后吧,前端就是一个约定大于规范的地方,就没有一个最权威的规范。所以一般就是开工之前,大家坐在一起,约定一下。目前最适合的吧,就是一个tab的缩进,相当于4个空格。
本月底,华南地区规模最大的制造业展会深圳机械展将着力聚焦机器人。可以预见的是,近两年风靡珠三角的机器人今年将延续之前的热度在珠三角发酵。 诚然,若没有需求,就不能催生产业发展空间,珠三角庞大的制造型企业对“机器代人”的强烈渴求成为机器人产业发展的助力器。 在珠三角的很多生产车间里,或出于替代人工的未雨绸缪,或出于先行试吃的气魄,机器人已渐替代人工。 成本收益 喜:有企业两年投入2.7亿,年均节省人力成本1.8亿 机器人应用这笔账怎么算? 而经过一番“机器换人”之后,该企业工人数量从最高峰时的6000人降至目前的2000人左右,而每年的销量却比往年高出不少。“最开始的投入是有点大,但现在看来是值得的。”该负责人说。 忧:暂无回报,还处于观察阶段 很多大型企业作为工业机器人试吃的先行者,数年经营投入已稍有成效,但对于一些发展中的小型企业来说,引进机器人则是一个更加艰巨的行为,其成本收益情况也同样不明朗。
Dependence Inversion Principle,DIP"依赖倒置原则",依赖倒置的原始定义是: Hign level modules should not depend ; 高层模块依赖抽象层:高层模块基于抽象层编程; 低层模块依赖抽象层:低层模块继承或者实现抽象层; 细节:实现接口或者继承抽象类而产生的类; 模块间的依赖通过抽象发生 ,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生的;接口或者抽象类不依赖于实现类;实现类依赖接口或者抽象类,核心思想是面向接口编程; 采用依赖倒置原则可以减少类之间的耦合性, 提高系统的稳定性; 举个例子: ? 最佳实践 依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块彼此独立,不互相影响,实现模块间的松耦合,我们在项目中应该尽量做到: 1.每个类尽量都有接口或者抽象类,或者抽象类和接口两者都具备
"里氏替换原则"是类的设计原则之一,我们使用"3H"学习法对其进行拆解; why(目的):为什么要学习"里式替换原则",我们都知道面向对象的三大特性:封装、继承、多态,该原则就是对良好的"继承关系 接下来我们开始进行具体的学习; 概念:LSP,"里式替换原则",凡是在父类出现的场景中,将父类替换为子类,程序逻辑不变,反之则未必可以。 1.子类需要实现父类的抽象方法 2.子类尽量不要重写或覆盖父类中已经实现的方法 3.子类重载父类方法时,子类输入参数>=父类输入参数&子类输出参数<=父类输出参数 4.子类可以添加自己特有的新方法,原则上不建议 LSP经典例子:正方形和长方形不符合里式替换,设置宽、高后,长方形的体积=宽*高,正方形体积=高*高,子类无法替换父类,不符合里氏替换原则; 在策略模式中,客户端类依赖抽象父类,场景类使用时传入具体的策略子类 ,子类都实现了父类的抽象接口,可以互换,这就符合里式替换原则;
而一个遵循着好的开发规范以及拥有着良好设计原则的系统,往往可以节约大量的后期维护升级成本。说起设计,往往大家第一反应是设计模式,殊不知,二十几种设计其实都遵循着一些基本的设计原则。 S.O.L.I.D,是事实证明的良好设计原则。 如果不遵循该原则,直接大刀阔斧地修改了某对象的行为,而恰巧该对象被系统的其他部分依赖怎么办? 值得说明的一点是,该原则中的接口并不特指 Java 中的 interface ,而是类似于 API 中的 I一样的泛义的接口,抽象类甚至具体实现类都可能包含在这个概念中。 遵循良好的设计原则,有利于我们平常在开发中写出更可维护的代码,便于团队协作也有利于后来者。道理上讲,设计模式、设计原则等等,也理应成为OOP程序员之间的常用术语,这样一来,才能显得更具专业性。
Single Responsibility Principle SRP,"单一职责原则":一个类只负责一组相关的事情,对应到代码中就是:一个类有多个方法,这些方法时相关的。 对于接口一定要做到单一职责原则: ? ? ? ? 对于类来说,尽量做到单一职责原则,一个多职责的类可以通过拆分、抽象、组合来实现单一职责原则。 ? ? ? ? ? ? 单一职责原则只适合那些基础类,而不适合基于基础类构件的复杂的聚合类,在"办公一体机"中,"打印机"、"复印机"、"扫描仪"、"传真机"都是基础类,每个类承担一个职责,而办公一体机是"聚合类",同事具备四种功能 单一职责原则的优点: 1.职责减少,类的复杂性降低,职责明确; 2.可读性提高,复杂性降低; 3.可维护性提高; 4.一个接口的修改只对相应的实现类有影响,对其他接口无影响; 原则虽好,但是还要掌握一个度吧 ,不要过渡设计,原则帮助我们写出更优雅、更具有扩展性、松耦合的代码设计,根据具体情况而定,要灵活的运用;
Least Knowledge Principle LKP,"迪米特原则":一个对象应该对其他对象有最少的了解。 通俗的说就是,一个类应该对自己需要耦合或调用的类知道的最少,你(被耦合或调用的类)的内部是如何的复杂和我没关系,我就知道你提供这么多的public方法,我就调用这么多方法,其他的我一概不关心。 迪米特原则的核心就是解耦合,它对类的低耦合提出一些要求: 只和朋友交流。 朋友的定义:出现在成员变量、方法的输入输出中的类称为朋友类,而出现在方法体内部的类不属于朋友类。 ? ? ? ? 以上代码中,Teacher类与入参GroupLeader为朋友关系,但是与方法中的Girl也有了交流,破坏了Teacher类的健壮性,方法时类的一个行为,类竟然不知道自己的行为与其他类产生关联,违反了迪米特原则 2.朋友间是有距离的。
每个资源要么已经分配给了一个进程,要么就是可用的。 2)占有和等待条件。已经得到了某个资源的进程可以再请求新的资源。 3)不可抢占条件。 已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。 4)环路等待条件。 死锁发生时,系统中一定有由两个或两个以上的进程组成的一条环路,该环路中的每个进程都在等待着下一个进程所占有的资源。 死锁发生时,以上四个条件一定是同时满足的。 如果其中任何一个条件不成立,死锁就不会发生。
摘自Jez Humble David Farley《持续交付:发布可靠软件的系统方法》 为软件的发布创建一个可重复且可靠的过程 这个原则是我们写这本书的一个目标:让软件发布成为一件非常容易的事情。 事实上,它的确应该是件很容易的事,因为在发布之前,对发布流程中的每一个环节,你都已经测试过数百次了。它就应该像单击一个按钮那么容易。 这种可重复性和可靠性来自于以下两个原则: 几乎将所有事情自动化; 将构建、部署、测试和发布软件所需的东西全部纳入到版本控制管理之中。 归根结底,软件部署包括三件事: 提供并管理你的软件所需要的运行环境,这包括硬件配置、所依赖的软件、基础设施以及所需的外部服务; 将你的应用程序的正确版本安装在其之上; 配置你的应用程序,包括它所需要的任何数据以及状态 将几乎所有事情自动化 把所有的东西都纳入版本控制 提前并频繁地做让你感到痛苦的事 内建质量 “DONE”意味着“已发布” 交付过程是每个成员的责任 持续改进
信号产生时异步的:对于一个进程不知道什么时候会收到信号,他只能先做自己的事情,信号产生时也不知道进程在干什么,所以是异步的!!! 是对应的6号信号(终止会打印Aborted!)其特殊的性质是可以被捕捉,但是进程还是会被终止掉,就是为了防止发生所有信号都被捕捉,没有信号可以终止的情况,9号信号和19号信号不能被自定义捕捉!!! alarm的本质是通过时间戳来比对,在设置闹钟的那一刻,操作系统会获取当前时间戳,然后加上闹钟时间得到一个新的时间戳。在以后的运行中不断和系统时间戳进行比对,相等的时候是就是闹钟的结束时刻!!! 段错误也是硬件的问题,空指针无法通过页表(实际上是MMU内存管理模块进行操作)映射到物理地址,会发生错误! CR2 - 控制寄存器2: 用于存储导致页错误的线性地址,当发生页错误异常时,CPU会自动将出错的线性地址加载到CR2中。