1.当某个计算正确性取决于多个线程的交替执行时序时,那么就会发生竞态条件,最常见的竞态条件就是先检查后执行。
2.先检查后执行的一种常见情况就是延迟初始化。(单例模式)
3.为了线程安全,先检查后执行的这种操作必须要时原子性的,java里面用加锁的方式来保证原子性。
4.要保持状态的一致性,就需要在单个原子操作中更新所有相关的状态变量。
5.获得内置锁的唯一途径就是进入这个锁保护的同步代码块获方法。
6.锁重入以为着锁的操作粒度时线程不是调用
7.对于可能被多个线程同时访问的可变状态变量,在访问它时都需要持有同一个锁,在这种情况下,我们称状态变量是由这个锁保护的。
8.每个共享和可变的变量都应该只由一个锁来保护,从而时维护人员指导时哪一个锁。
9.对于每个包含多个变量的不变性条件,其中涉及的所有变量都需要由同一个锁来保护。
10.通常,在简单性与性能之间存在着互相制约因素。当实现某个同步策略时,一定不要盲目的为了性能而牺牲简单性。
11.当执行时间较长的计算或者可能无法快速完成的操作时,(如网路IO或控制台IO),一定不要持有锁。
12.synchronized同步还可以实现:内存可见性。
13.只要有数据在多个线程之间共享,就使用正确的同步。
14.即使不考虑数据失效性问题,在多线程程序中使用 共享且可变的long和double等类型变量也是不安全的,除非用关键字volatitle来声明他 们,或者用锁保护起来。
15.加锁的含义并不仅仅局限于互斥行为,还包括内存课件性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步。
16.读取volatitle类型的变量时总会返回最新写入的值。volatitle不会被缓存在寄存器或者对其他处理器不可见的地方。
17.仅当volatitle变量能简化代码的实现以及同步策略时,才应该使用它们。如果在验证正确性时需要对可见性进行复杂的判断,就不要使用volatitle。volatitle变量的正确使用方式包括:确保它们自身状态的可见性,确保它们所引用对象的状态的可见性,以及标识一些重要的程序生命周期事件的发生。
18.volatitle变量的一种经典用法:检查某个标记以判断是否退出循环。
19.加锁机制既可以确保可见性又可以确保原子性,而volatitle只能确保可见性。
20.当且仅当满足一下条件时,才应该使用volatitle变量:
·对变量的写入操作不依赖变量当前的值,或者能确保只有单个线程更新变量的值。
·该变量不会与其他状态变量一起纳入不变性条件中。
·在访问变量时不需要加锁。
21.不要在构造过程中使this引用逸出。
22.如果仅在单线程内部访问数据,就不需要同步,这种技术被称为线程封闭。局部变量和ThreadLocal类可以用来维持线程的封闭性。
23.只要你能确保只有单个线程对共享的volatile变量执行写入操作,那么就可以安全的在这些共享的volatile变量上执行读取修改写入操作。
24.Thread Local提供了get与set等访问接口的方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程set时设置的最新值。