这本书火也挺大的,但是是在比较难看的进去,尤其是第二部分,第一部分记录下来,理论知识还是可以的。
第二章,线程安全性
-
什么是线程安全。多个线程访问某个类时,不管运行环境采用的何种调度方式或者这些线程如何交替执行,调用者无需额外的同步或协同,这个类都能表现出正确的行为,这个类就是线程安全的。
-
原子操作。两个操作之间没有任何交集,相对于a来说,b要么已经执行完了,要么还没有执行。如果所有都是原子的,就不存在竟态了。我们可以尽量用现有的线程安全对象来管理类状态。
-
加锁机制。一,内置锁,比如synchronized,但是有性能问题,同一时刻只有一个线程可以访问。二,重入。避免了死锁的发生。三,用锁来保护状态。就是一个对象对本身所有访问可变状态的代码路径进行同步,防止并发访问。保护了所有变量,比如vector。四,滥用sync这个有性能问题和活跃性问题。可以拆分下,变成多个原子性的操作。但是要考虑到安全性和性能的一种平衡。
第三章,对象的共享。
-
Volitile是一个轻量级的同步。使用起来不用阻塞这些,但是使用条件有一定的限制。
-
线程封闭:就是某个对象封闭在某个线程中,即使对象本身不是线程安全的。java语言及核心库提供了一些机制帮助线程封闭性,比如局部变量和threadlocal类。
-
Ad-hoc的封闭技术比较脆弱,别用,用下面两种。
-
一,栈封闭。只有局部变量才能访问对象,封闭在方法中。基本类型的局部变量或者引用变量的线程封闭性。
-
二,threadlocal类。线程封闭性的一种更规范方法,这个类使线程中的某个值与保存值的对象关联起来。这里注意:具体的和valitile的区别需要深入研究。
-
另一种方法是不变性,不会改变的对象,比如final域
第四章,对象的组合
-
本章介绍一些模式是类更强大,更容易成为线程安全的。
-
锁的正确性。若没有就添加,put(x),比如这个方法加了个同步锁,其实并不是原子的,应该对list加锁,而不是这个x。
-
借助于文档的维护,有时也是一种办法,不然通过猜测只会降低准确性。
第五章,基础构建模块
-
并发容器:concurrenthashmap,使用分段锁,粒度更细,并发下吞吐量更高,单线程下损失性能也小。他的size和isempty只是估计值,因为一直在变动,并发下用这两个方法也没意义。并发下比较好,如果加锁独占访问的话就不要用这个。对很多复合操作提供了原子操作,比如若没有就添加。copyonwritearraylist用来代替同步list
-
阻塞队列,和生产者消费者模式挺好的将两者代码解偶,但是也是默认消费者的速度能赶上生产者的速度。所以一般也不会设置边界,隐藏一些问题,可以用多种list实现。
-
还有一种双端队列,自己的处理完了,取别人的。适用于即是生产者也是消费者问题,当执行某个工作时可能导致更多的工作。
-
中断方法。如果被中断,一般来说会抛出interruptedexception异常,一般有两种做法,一,传递异常给调用者,不捕获不抛出,然后在执行某种简单的清理后再次抛出异常。二,有的情况不能抛出异常,比如runnabe,需要捕获,并恢复中断状态,高层代码看到了引发了一个中断。
-
构建高效且可伸缩的结果缓存。重点是为缓存服务的,一,用hashmap需要用sync修饰,但是可伸缩性差,很多线程会被阻塞。二,concurrent代替,可以并发访问了,但是有个性能问题,多个线程可能会重复计算,假如每个开销大的话,更是浪费,可能他们计算的结果是一样的,最好能识别出,有人在计算27了,我就不算了,等就行了。三,那就是future,他会查询某个计算是否开始,开始了就等,没开始就注册。而2是查询某个计算是否结束。三是完美的,并发和性能,仍然有小概率会同二,有两个计算结果一样的线程,但远远小于。