1、永远不要在循环之外调用wait方法
原因:尽管不满足被唤醒条件,但是由于其他线程调用notifyAll()方法会导致被阻塞线程意外唤醒,此时执行条件并不满足,他将破坏被锁保护的约定关系,导致约束时效,引起意想不到的结果。一般用while循环
2、唤醒线程是应该用 notify()还是 notifyAll()
当你不知道究竟该调用哪个方法时,保守的做法是调用notifyAll()唤醒所有等待的线程。从优化的角度看,如果处于等待的所有线程都在等待同一个条件,而每次只有一个线程可以从这个条件中被唤醒,那么就应该选择调用notify。
3、volatile关键字使用(参考Netty权威指南带目录完整版.pdf第480页)
volatile修饰变量的作用:线程可见性(当一个线程修改,其它线程可以立即看到最新的修改)、禁止指令重排序优化。
volatile主要解决了可见性问题,并不保证互斥性,也就是说多个线程并发修改变量时依旧会产生多线程问题。
volatile最适合使用的是一个线程写、其它线程读的场合,如果有多个线程并发写操作,仍然要使用锁或线程安全的容器或原子变量来代替。
4、读写锁使用场景
主要用于读多写少的场景;
读写锁是可重入、可降级的,一个线程获取读写锁后,可以继续递归获取,从写锁可以降级为读锁,以便快速释放锁资源;
ReentrantReadWriteLock 支持获取锁的公平策略;能获取更好的性能同时兼顾公平;
读写锁支持非阻塞的尝试获取锁,如果失败直接返回false,而不是同步阻塞;(多个线程同步读写某个资源,当发生异常或需要释放资源时,由哪个线程释放是个难题,因为某些资源不能重复释放或执行,这样通过tryLock方法获取锁,拿不到说明被其它线程占用,直接退出即可)
获取锁后一定要释放锁,否则会发生锁溢出异常。通常通过finally块释放锁,如果tryLock,获取锁成功才要释放。