1、安全性问题

就是线程安全问题,除了加锁还有就是不要共享变量,在18年我接手的一个照片管理后台(AI模块管理)班牌要来获取照片,每个班牌都要获取,每个班牌都会在服务端生成一个压缩包,开始的时候就只有一个唯一的压缩包,每个班牌都公用,就会导致第一个班牌生成了压缩包,第二个班牌去访问的时候错拿了,如果没有并发还好,并发的时候就坑了,然后我改成了每个班牌在后台都有一个文件夹,就是不让他发生竞争 ,其实这个思想和ThreadLocal是一样的。就是多个线程不共享变量。

2、活跃性问题

活锁

就是俩个线程都互相谦让一把锁

解决办法

等待一个随机事件,raft也用到了等待一个随机时间。

饥饿

就是线程一直轮不到,

解决办法

公平锁

3、性能问题

有个阿姆达尔(Amdahl)定律,代表了处理器并行运算之后效率提升的能力,它正好可以解决这个问题,具体公式如下image.png

公式里的 n 可以理解为 CPU 的核数,p 可以理解为并行百分比,那(1-p)就是串行百分比了,也就是我们假设的 5%。我们再假设 CPU 的核数(也就是 n)无穷大,那加速比 S 的极限就是 20。也就是说,如果我们的串行率是 5%,那么我们无论采用什么技术,最高也就只能提高 20 倍的性能

性能一般包括三个方面

  1. 吞吐量
  2. 延迟
  3. 并发量

    kafka也是这么衡量的。

课后思考

  1. void addIfNotExist(Vector v,
  2. Object o){
  3. if(!v.contains(o)) {
  4. v.add(o);
  5. }
  6. }

答案

Vector实现线程安全是通过给主要的写方法加了synchronized,类似contains这样的读方法并没有synchronized,该题的问题就出在不是线程安全的contains方法,两个线程如果同时执行到if(!v.contains(o)) 是可以都通过的,这时就会执行两次add方法,重复添加。也就是老师说的竞态条件。