JUC——线程同步锁(ReentrantLock)

时间:2023-02-13 13:53:56

ReentrantLock简介

ReentrantLock是一个可重复的互斥锁,又被称为独占锁,可重入的意思是:ReentrantLock锁可以被单个线程多次获取。但是在同一个时间点只能被一个线程锁持有

ReentrantLock使用一个FIFO(先进先出)的等待队里来管理获取该锁所有线程的。

 

ReentrantLock是一个独占锁,在获取锁的之后其所有的操作都是线程独享的,其他的线程在没有获取到锁之前都需要等待。

public class ReentrantLock implements Lock,java.io.Serializable

ReentrantLock之中分为公平锁与非公平锁,它们的区别体现在获取锁的机制上是否公平以及执行速度上。、

这两种锁的启用也是非常容易控制的,这个类提供的构造方法如下:

  • 无参构造(非公平锁,NonfairSync)
    public ReentrantLock() {
        sync = new NonfairSync();
    }
  • 有参构造
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    //fair = true,表示公平锁,FairSync
    //fair = false,表示非公平锁,NonfairSync

     

ReentrantLock继承结构

JUC——线程同步锁(ReentrantLock)

范例:使用ReentrantLock定义一个多线程卖票的处理程序

package so.strong.mall.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Ticket {
    private Lock myLock = new ReentrantLock();  //非公平锁
    private int count = 10; //一共10张票
    public void sale() {
        myLock.lock(); //进入到阻塞状态,一直到unlock执行后解除阻塞
        try {
            if (this.count > 0) {
                System.out.println(Thread.currentThread().getName() + "卖票,ticket=" + this.count--);
            }
        } finally {
            myLock.unlock(); //不管最终结果如何一定要进行解锁
        }
    }
}


public class TestDemo {
    public static void main(String[] args) {
        final Ticket ticket = new Ticket(); //多线程要共享同一个数据资源
        for (int i = 0; i < 6; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        ticket.sale(); //卖票处理
                    }
                }
            }).start();
        }
    }
}
Thread-0卖票,ticket=10
Thread-0卖票,ticket=9
Thread-0卖票,ticket=8
Thread-0卖票,ticket=7
Thread-0卖票,ticket=6
Thread-0卖票,ticket=5
Thread-0卖票,ticket=4
Thread-2卖票,ticket=3
Thread-2卖票,ticket=2
Thread-2卖票,ticket=1

当前的代码要比直接使用synchronized更加容易,而且锁的处理机制更加的直观。通过查看源代码可以发现,使用lock()进行锁定的时候会考虑两种情况:

Sync-java.util.concurrent.locks.ReentrantLock

  •  FairSync-java.util.concurrent.locks.ReentrantLock
  •  NonFairSync-java.util.concurrent.locks.ReentrantLock

在进行公平锁处理的时候每当锁定一个线程对象就会使用“acquire(1)”方法进行表示:

final void lock() {
   if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
   else
        acquire(1);
}

在进行解锁时会使用一个"sync.release(1)”释放方法, 1 表示释放一个:

public void unlock() {
   sync.release(1);
}