码迷,mamicode.com
首页 > 其他好文 > 详细

重入锁

时间:2017-02-18 11:04:41      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:count   ued   super   mon   队列   线程   分享   ase   test   

重入锁ReentrantLock

  1. 支持一个线程对同一个资源进行多次加锁。
  2. 支持获取锁时的公平和非公平性选择

锁获取的公平性问题:

先对锁进行获取的请求一定先被满足,那么这个锁是公平的,反之,是不公平的。ReentrantLock提供了一个构造函数(传人一个布尔值),来控制锁是否是公平的 

1.实现重进入

  1. 锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取。 
  2. 线程重复n次获取了锁,随后在第n次释放该锁后,其他线程才能够获取到该锁。锁被获取时,计数自增,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放。

 

//非公平获取锁
final
boolean nonfairTryAcquire(int acquires) {   final Thread current = Thread.currentThread();   int c = getState();   if (c == 0) {     if (compareAndSetState(0, acquires)) {       setExclusiveOwnerThread(current);       return true;     }   } else if (current == getExclusiveOwnerThread()) {     int nextc = c + acquires;//成功获取锁的线程再次获取锁,只是增加了同步状态值     if (nextc < 0)
       throw new Error("Maximum lock count exceeded");
    setState(nextc);
    return true;
  }   
return false; }

 

//释放锁
protected
final boolean tryRelease(int releases) {   int c = getState() - releases;//在释放同步状态时减少同步状态值   if (Thread.currentThread() != getExclusiveOwnerThread())     throw new IllegalMonitorStateException();   boolean free = false;   if (c == 0) {     free = true;     setExclusiveOwnerThread(null);   }   setState(c);   return free; }

 

2.公平与非公平获取锁

  公平与非公平获取锁的区别 :锁的获取顺序是否符合FIFO 

//公平获取锁
protected final boolean tryAcquire(int acquires) {
  final Thread current = Thread.currentThread();
  int c = getState();
  if (c == 0) {
    if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
      setExclusiveOwnerThread(current);
      
return true;     }   } else if (current == getExclusiveOwnerThread()) {     int nextc = c + acquires;     if (nextc < 0)       throw new Error("Maximum lock count exceeded");     setState(nextc);     return true;   }
  return
false; }

该方法与nonfairTryAcquire(int acquires)比较,唯一不同的位置为判断条件多了hasQueuedPredecessors()方法,即加入了同步队列中当前节点是否有前驱节点的判断,如果该方法返回true,则表示有线程比当前线程更早地请求获取锁,因此需要等待前驱线程获取并释放锁之后才能继续获取锁 

测试公平和非公平锁在获取锁时的区别

public class FairAndUnfairTest {
  private static Lock fairLock = new ReentrantLock2(true);
  private static Lock unfairLock = new ReentrantLock2(false);
  @Test
  public void fair() {
    testLock(fairLock);
  } 
  @Test   
public void unfair() {     testLock(unfairLock);   }
  private
void testLock(Lock lock) {     // 启动5个Job(略)   }
  private
static class Job extends Thread {     private Lock lock;     public Job(Lock lock) {       this.lock = lock;     }
    public
void run() {// 连续2次打印当前的Thread和等待队列中的Thread(略)     }   }
  private
static class ReentrantLock2 extends ReentrantLock {     public ReentrantLock2(boolean fair) {       super(fair);     }
    public Collection
<Thread> getQueuedThreads() {       List<Thread> arrayList = new ArrayList<Thread>(super.getQueuedThreads());       Collections.reverse(arrayList);       return arrayList;     }   } }

 

 

技术分享

 

 观察表5-6所示的结果(其中每个数字代表一个线程),公平性锁每次都是从同步队列中的第一个节点获取到锁,而非公平性锁出现了一个线程连续获取锁的情况。 由于刚释放锁的线程再次获取同步状态的几率会非常大 ,这样就减少了因锁切换而导致的线程上下文切换的开销



 

重入锁

标签:count   ued   super   mon   队列   线程   分享   ase   test   

原文地址:http://www.cnblogs.com/jimboi/p/6412603.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!