java并发编程实战(笔记)

第1章 简介

略,觉得没有必要写笔记,一堆介绍,没有什么实际作用。

第2章 线程安全

2.1 什么是线程安全?

默认情况下,我们创建n个线程,线程的执行顺序不是由我们程序员而决定的,而是由cpu的调度器决定,然后这并不是我们想要的效果,我们希望可以控制线程,操纵多线程,来帮助我们完成多个任务。
那什么是线程安全啊呢?
多线程在共同使用一个变量的时候,会出现争夺变量的情况,最后的结果就是,计算完毕后,计算的结果是错误的,于是乎我们需要让线程有序,不出现争夺变量的情况,有序的手段就是对变量上锁,这样就可以保证线程是安全的。

2.2原子性

原子是不可分割的,我觉得在线程中谈原子性,应该是多个线程访问同一个变量的时候,在同一时刻,只能有一个线程去读写变量,只要这个线程没有读写完毕,其他线程就无法去读写变量。

2.2.1竟态条件

Condition,线程竞争的条件,通过创建不同Condition,notFull、notNull之类的对象,来达到精确控制锁的目的,一般和重入锁结合使用。

2.3加锁机制

2.3.1内置锁

synchronized,修饰代码块,或者修饰方法体

2.3.2重入锁

ReentrantLock

 class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

2.4用锁来保护状态

用锁可以让公共的变量处于独占状态,这样就可以保证在多线程的环境中,每个线程不会获取到错误的数据。

2.5活跃性与性能

不要对执行时间较长的计算,或者可能无法快速完成的操作加锁。
尽量缩小synchronized的范围,范围比较大的话,作者说这属于不良并发,不良并发就是为了安全,而放弃了大量的性能。

第3章 对象的共享

3.1 可见性

举个例子,来说明可见性。
有线程1、2、3,有int n = 0;
在多线程的环境中,假设线程1争取到了读写权,把n修改成了1,如果程序具有可见性,那么2、3是可以看到n的最新值,也就是1。
这就是变量的可见性,我觉得书中想表达的就是这个意思。

3.1.1 失效的数据

作者写了一个demo,证明了在多线程的情况下,线程会读取到错误的数据。
避免的方式就是使用同步机制。。。

3.1.2 非原子的64位操作

java内存模型中规定,变量的读操作或者写操作必须是原子操作,但是,对于非volatile的long和double变量,jvm中允许将64位的读写操作拆成2个32位的操作。所以在多线程的环节中执行上述操作,可能会随机的获取到2个32位操作中的某个,所以在多线程的环境中公共变量就用volatile来修饰,这样就安全了。

3.1.3 加锁与可见性

书中画了一张图,图中有线程A和线程B,线程A先执行,B后执行,线程A对变量做的修改,线程B执行的时候是可以获取到之前线程A修改的值,就是可见性。

3.1.4 volatile变量

论述了volatile只具有可见性,volatile是一种轻量级的加锁机制,适用场景一般就是发布状态。
volatile和synchronized的取舍,volatile能做到的,用synchronized也同样可以做到,只是在一些少数情形下,使用volatile更优而已。

3.2发布与逸出

发布:把对象用public 和 static 修饰,就可以是发布了
逸出:简而言之就是一些私有属性,本来是封装于Class中,是不应该发布的,但是由于一些其他原因变为共有状态,不具有私有性。
书中介绍,防止逸出的办法就是使用工厂方法,来创建对象。

3.3线程封闭

你可能感兴趣的:(理论篇)