Java并发编程读书笔记(一)

时间:2023-01-02 09:54:27

----------------------------------------------《Java并发编程实战》读书笔记------------------------------------------------------------------------------

第二章 线程安全性

java同步 1、sychronized
  2、volatile类型
  3、显示锁
  4、原子变量
性能优化之原则:首先保证代码能正确运行,然后再提高代码速度。并且,只是当性能测试结果和应用需求需要提高性能、
并且测量结果表明该种优化在实际环境中确实能够带来性能提升时,才进行优化。

1、无状态对象一定是线程安全的,例如无状态servlet (大多数servlet都是无状态的)

2、原子性
   比如 count++就不是原子性操作,它包括了 读取count —— count值+1 —— 新值放回count 三个操作
   这样的非原子操作在多线程环境下就会出现线程安全性问题
  
   并发编程中,由于多个线程交替执行不恰当的执行时序而出现不正确的结果,称为竞态条件。
   最常见的一种静态条件: 先检查,后执行。 即通过一个可能已经是失效的监测结果来决定下一步的执行动作。
  
   原子变量
      多线程累加计数使用java.util.concurrent.atomic.AtomicLong类型代替long,其incrementAndGet()方法实现自增加1,这是线程安全的。
     
      原子变量不能解决所有并发问题,只能对某个变量进行原子操作,如果是一段过程,则没法进行原子操作。多个变量进行依赖的情况也无能为力。
      例子:(在一个servlet.service()方法里,建两个AtomicReference存一对值key-value,每次查询key命中就返回value,如果不命中就设置新的key-value)
     
3、   内置锁
       即代码同步块synchronized ,是一种互斥机制,任何一个执行同步代码块的线程,都不可能看到其他线程在执行由同一个锁保护的同步代码块。
       好比是一个每次只能出现一个人的房间,其他人要想进入这个房间,必须等里面的这个人出去,并且每次房间里最多只能有一个人。
      
       e.g. 可以把上面的那个servlet的service()方法设置为public synchronized void service(),保证了线程安全性,但性能太低。
          每次只有一个线程能访问service方法,而service又是servlet的主要方法,这相当于servlet变成单线程的了
          
4、   重入
       指的是java内置锁的一种特性,线程在重复获取一个已经由它持有内置锁的时候,是可以成功的。
       public class Widget{
         public synchronized void doSomething(){}
        }
        
        public class LoginWidget extends Widget{
         public synchronized void doSomething(){
           ...
           super.doSomething();
          }
         }
    子类调用自己的doSomething方法持有锁,然后在方法体内再调用父类的doSomething方法,请求的是同一个锁,
    如果没有重入特性,那么此处将会发生死锁。

5、  同步的两个方面 
          1、线程安全性
   2、内存可见性(memory visibility)
          线程在使用一个资源的时候其他线程不可以修改这个资源;同时,当线程对一个资源的状态进行了修改之后,其他线程应该可以看得见这个变化。即为内存可见性。