Posted on 2010-12-03 10:11
杨罗罗 阅读(1827)
评论(0) 编辑 收藏 所属分类:
java.thread
AQS中有一个state字段(int类型,32位)用来描述有多少线程获持有锁。在独占锁的时代这个值通常是0或者1(如果是重入的就是重入的次数),在共享锁的时代就是持有锁的数量。
自旋等待适合于比较短的等待,而挂起线程比较适合那些比较耗时的等待。
锁竞争
影响锁竞争性的条件有两个:锁被请求的频率和每次持有锁的时间。显然当而这二者都很小的时候,锁竞争不会成为主要的瓶颈。但是如果锁使用不当,导致二者都比较大,那么很有可能CPU不能有效的处理任务,任务被大量堆积。
所以减少锁竞争的方式有下面三种:
- 减少锁持有的时间
- 减少锁请求的频率
- 采用共享锁取代独占锁
死锁
1.一种情况是线程A永远不释放锁,结果B一直拿不到锁,所以线程B就“死掉”了
2.第二种情况下,线程A拥有线程B需要的锁Y,同时线程B拥有线程A需要的锁X,那么这时候线程A/B互相依赖对方释放锁,于是二者都“死掉”了。
3.如果一个线程总是不能被调度,那么等待此线程结果的线程可能就死锁了。这种情况叫做线程饥饿死锁。比如说非公平锁中,如果某些线程非常活跃,在高并发情况下这类线程可能总是拿到锁,那么那些活跃度低的线程可能就一直拿不到锁,这样就发生了“饥饿死”。
避免死锁的解决方案是:
1.尽可能的按照锁的使用规范请求锁,另外锁的请求粒度要小(不要在不需要锁的地方占用锁,锁不用了尽快释放);
2.在高级锁里面总是使用tryLock或者定时机制(就是指定获取锁超时的时间,如果时间到了还没有获取到锁那么就放弃)。高级锁(Lock)里面的这两种方式可以有效的避免死锁。