JAVA多线程学习笔记--高洪岩版第二章以及第三章学习笔记

第二章重点内容

线程不安全产生的问题:脏读(读出的数据为更改后额数据,如:线程A更改数据并打印数据,在刚要执行打印语句时线程B更改数据值,线程A打印不出想要的值,此为脏读)

实现同步的锁对象
同步方法的锁为运行该方法的对象
静态同步方法的所谓运行该方法的对象的class文件
同步代码块的锁对象为synchronized(锁)中的(..)内对象

锁重入
一个线程调用一个对象的synchronized方法,在方法内还可以调用该对象的其他synchronized方法,也就是可重复获得对象锁,可重复锁也支持在子父类继承环境,也就是说子类可以通过“可重入锁”调用父类的同步方法

*出现异常时锁释放

*同步不能被继承

同步代码块对某些局部代码进行同步,也就是书上所说的一半同步一半异步

同步代码块中的锁为非this的好处(书上的原话):如果在一个类中有很多个synchronized方法,这时虽然能实现同步,但会受到阻塞,所以影响运行的效率,使用非this方法不与其他同步方法抢this这个锁,大大提高运行效率

*String锁的常量池特性(不建议使用String为锁)

内置类与静态内置类
静态内置类可不需要先new 外面的类而直接new里面的
静态内置类的同步方法锁对象为this

锁对象的改变
在一个线程执行同步代码时先确定锁对象,之后执行该同步代码会去拿第一次确认的锁对象(我是这么理解的,可能有错误),而锁对象的属性改变不会影响锁的确认及获取

volatile关键字
该关键子的作用是使变量多个线程之间可见
该关键字的作用是强制从公共堆栈取变量值而不是从线程私有数据栈中取变量值(每一个线程多有各自的堆栈)
volatile关键字的缺陷,不支持原子性(也就是说volatile适合读数据不适合写数据)
http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
这边解释的比较清楚
大致意思是:当new一个线程后会为该线程分配属于该线程自己的堆栈,在线程运行及start后,线程会将主内存的自己需要的对象复制到自己的堆栈中,在run方法调用时线程内存与主内存无交互,线程结束后,线程会将内存的内容更新到主内存中。
其他非原子操作:i++,i–,等等
java的原子类
AtomicInteger,AtomicDouble…等等

synchronied实现变量线程之间可见
http://www.cnblogs.com/zhilu-doc/p/5778180.html
他的原理是:
线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁和解锁需要是同一把锁)
 注:线程解锁前对共享变量的修改在下次加锁时对其他线程可见

第三章线程之间的通讯

等待通知机制(wait/notify)
*必须在同步代码中使用,lock.wait,lock.notify
wait使当前执行的代码进行等待,将当前线程放入预执行队列,并在所在代码处停止执行,直到通知或被中断,在wait前需获得对象锁,执行wait后,释放锁
notify也在同步代码块中使用,notify后,线程规划器会随机挑选一个在同步代码锁对象上wait的线程唤醒,在notify所在的同步代码执行完成后,选择唤醒的线程进行执行,notify本身不释放锁
notifyAll唤醒所有在锁上的线程

每个锁都有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列为将要获得锁的线程,阻塞队列为被阻塞的线程

*生成者消费者

线程之间的通讯,通过管道流,pipedInputStream,pipedOutputStream,pipedReader,pipedWriter

join方法
join方法使当前线程等待,直到调用该方法的线程运行完在执行当前线程,join内部使用的事wait
使用join会释放当前线程的锁,如果当前线程加锁了的话

ThreadLocal
ThreadLocal会为每个线程分配一个Object,每个线程可以获得各自的Object,虽然在一个共有对象内,
也就是说:类A里有个ThreadLocal属性,不同线程调用A中的ThreadLocal的set方法放入不同的值,不同线程在调用ThreadLocal的get方法时会获得自己set的值

InheritableThreadLocal会使子线程获得父线程继承下来的值,如果子线程未设置

你可能感兴趣的:(多线程学习)