您的当前位置:首页正文

手写ReentarntLock

2024-11-29 来源:个人技术集锦
/****
 * 通过重写Lock接口来实现ReentrantLock来理解ReentrantLock原理
 */
public class JamesReentrantLock implements Lock {
    //标记重入次数的count值
    AtomicInteger count=new AtomicInteger(0);
    //锁的持有者
    AtomicReference<Thread>owner=new AtomicReference<>();
    //等待队列
    private LinkedBlockingQueue<Thread> waiters=new LinkedBlockingQueue<>();
    @Override
    public boolean tryLock() {
        //判断count是否为0,若count!=0,说明锁被占用
        int ct=count.get();
        if(ct!=0){
            //判断锁是否被当前线程占用,若被当前线程占用,做重入操作,count+=1
            if(owner.get()==Thread.currentThread()){
                count.set(ct+1);
                return  true;
            }else {
                //若不是当前当前线程占用,互斥,抢锁失败。return false;
                return  false;
            }
        }else {//若count=0.说明锁未被占用,通过CAS(0,1)来抢锁
            if(count.compareAndSet(ct,ct+1)){
             //若抢锁成功,设置owner为当前线程的引用
             owner.set(Thread.currentThread());
             return true;
            }else {
                return  false;
            }

        }
    }
    @Override
    public void lock() {
        //尝试抢锁,tryLock()成功的话,则直接抢到了锁;tryLock()失败进行如下操作
        if(!tryLock()){
            //如果抢锁失败,进入等待队列
            waiters.offer(Thread.currentThread());
            //自旋
            for (;;){
                //判断是否是队列头部,如果是再次发起抢锁;头部有两种情况,一是队列此时为空直接再次抢锁,二是队列被唤醒,如果处   于队列头则再次进入抢锁,应该属于公平锁
                Thread head=waiters.peek();
                if(head==Thread.currentThread()){
                 //再次尝试抢锁
                 if(!tryLock()){
                     //若抢锁失败,挂起线程,继续等待
                     LockSupport.park();
                 }else {
                     //若成功,就出队列
                     waiters.poll();
                     return;//退出自旋
                 }
                }else{
                    //如果不是waiters队首,就挂起线程
                    LockSupport.park();
                }

            }
        }
    }

    @Override
    public void unlock() {
      if(tryUnlock()){
          Thread th=waiters.peek();
          if(th!=null){
              LockSupport.unpark(th);
          }
      }
    }

    public  boolean tryUnlock(){
        //判断,是否是当前当前线程占有锁,若不是抛异常
        if(owner.get()!=Thread.currentThread()){
            throw new IllegalMonitorStateException();
        }else {
            //如果是,就将count-1 若count变为0,则解锁成功,(因为当前操作是获取到锁才执行的,所以以下几个操作不会被分割)
            int ct=count.get();
            int next=ct-1;
            count.set(next);

            //判断count值是否为0
            if(next==0){
             owner.compareAndSet(Thread.currentThread(),null);
             return true;
            }else {
                return  false;
            }
        }
    }
}

static JamesReentrantLock lc = new JamesReentrantLock();
    private static int num = 0;
    public static void main(String args[]) throws InterruptedException {
     /*   for (int i=0; i<10; i++){
            new Thread(){
                @Override
                public void run() {
                    for (int j=0; j< 10000; j++){
                        //System.out.println(currentThread().getName()+ "....");
                        add();
                    }
                    System.out.println("done...");
                }
            }.start();
        }

        Thread.sleep(6000L);
        System.out.println(i);

    }*/
        int count = 2000;
        CountDownLatch countDownLatch = new CountDownLatch(count);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    lc.lock();
                    Thread thread = Thread.currentThread();
                    System.out.println("--start--"+thread.getName());
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num++;
                    System.out.println("--end--");
                    countDownLatch.countDown();
                }finally {
                    lc.unlock();
                }

            }
        };
        Thread thread = null;
        for (int i = 0; i < count; i++) {
            thread = new Thread(runnable,"t"+i);
            thread.start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--num--"+num);
    }
在这里插入代码片
显示全文