JAVA并发实践学习

来源:互联网 发布:mp3加背景音乐软件 编辑:程序博客网 时间:2024/05/19 01:06

1、对象的状态是由这存储在状态变量里的数据组成的,比如instance / fields ,
      也包含它所引用的对象的状态 , 当一个对象没有field的时候,它是线程安全的.
2、线程安全主要解决的问题是:受控制的并发访问数据
3、解决线程安全的三个方法:
      a、不要在线程间共享状态变量 b、使状态变量不可修改 c、使用同步机制访问状态变量
     (好的面向对象设计方法在设计线程安全的类时很有用:封装、恒常性、清晰的常量说明)
4、synchronized能够保证原子性操作和内存可视
      a、java变量: int i=0; i++;其中i++不是一个原子操作, 实质上是由三步操作完成:read , modify , write,
      在不保证操作原子性的情况下,可能出现两个相等的i值.check-then-set也是同样的道理.
      b、不加适当锁机制的共享变量,可能内存不可视.原因:一个线程修改它以后没有立即写回主存(可能还存在于高速缓存中),
      恰好另一线程正从主存中读取。
5、volatile关键字能够保证内存可视性,(写JAVA程序两年啦,才知道,唉,失败呀)。一个轻量级的synchronized , 但它不能保
      证原子性。
6、java.util.concurrent.atomic包下的原子类型可以解决原子性操作问题如:AtomicLong.
7、java中的锁实现依赖于一个AbstractQueuedSynchronizer的数据结构,其中有一个volatile int state的字段用于表示状态.
      此字段的修改是通过Unsafe.compareAndSwap*来实现(由native方法实现 ,依赖于具体的操作系统) .
8、公平锁与非公平锁: 简单的说公平锁就是按照AbstractQueuedSynchronizer中节点的顺序来依次获取锁(FIFO),非公平锁则
      有可能后来居上,使某些线程永远不能获取锁.
9、个人理解的线程安全的并发过程:
       多个线程同时访问同一个对象(应该是同一个lock) , 第一个到达的线程acquire成功修改state,标记当前排它线程为自己,
       然后执行,后来的线种只能park,被以链表的形式装进队列里面。当获取锁的线程执行完以后,就修改AQS的state,并调
       用其后继的unpark().实现的关键在于AbstractQueuedSynchronizer,它以链式结构组织线程,以state来标志可访问状态,
       其实就是通过state来实现序列化访问.
10、JAVA锁很多种, ReentrantLock , ReadLock , WriteLock等,其实现都依赖于一个继承AbstractQueuedSynchronizer的内部锁
        机制(内部类).看源码知道:ReentrantLock的lock方法实际上是NonfairSync的lock方法,NonfairSync就是继承AbstractQueuedSynchronizer
11、JAVA默认采用非公平锁,传说是因为公平锁需要额外的维护信息,而非公平锁不且实现了高速算法。