并发经验告诉我们:首先使用Java SDK中的并发包,迫不得已再使用低级的同步原语(synchronized/Lock/Semaphore等)。避免过早优化,等出现性能瓶颈后再去优化
synchronized和Lock
synchronized直接有一条happens-before原则,可以保证可见性; Lock同样保证可见性。
synchronized和Lock的区别在于: synchronized不能破坏不可抢占条件。synchronized 申请资源的时候,如果申请不到,线程直接进入阻塞状态了,而线程进入阻塞状态,啥都干不了,也释放不了线程已经占有的资源。
Lock能够 1.响应中断; 2.支持超时(如果线程在一段时间之内没有获取到锁,不是进入阻塞状态,而是返回一个错误,那这个线程也有机会释放曾经持有的锁); 3.非阻塞地获取锁(如果尝试获取锁失败,并不进入阻塞状态,而是直接返回,那这个线程也有机会释放曾经持有的锁)
重入锁
线程可以重复获取同一把锁。
addOne()时先获得一把锁,在1处get()仍需要锁,可以发现这两个锁是同一个,被获取了两次java 中ReentrantLock即为可重入锁,默认情况下为非公平锁。
这里需要补充一下公平锁和非公平锁:如果是公平锁,唤醒的策略就是谁等待的时间长,就唤醒谁,很公平;如果是非公平锁,则不提供这个公平保证,有可能等待时间短的线程反而先被唤醒。
锁的最佳实践
1.永远只在更新对象的成员变量时加锁 2.永远只在访问可变的成员变量时加锁 3.永远不在调用其他对象的方法时加锁
Condition 实现了管程模型里面的条件变量
老师的阻塞队列框架填充一下可以实现,自己写个demo。
网友评论