公平锁与非公平锁

ReentrantLock和synchronized的自JDK1.6以来主要的区别在于:1、等待可中断;2、公平锁与非公平锁;3、锁的多个条件。我们知道synchronized只能实现非公平锁,因此在需要使用公平锁的情况下会使用ReentrantLock,非公平锁和公平锁的区别在于会不会在锁释放时,新的线程是否会和AQS队列中的队首线程竞争锁。但是以上八股文的背法,为了更好的理解公平锁与非公平锁,笔者简单的模拟了公平锁和非公平锁的竞争的情况,详细的注释已经在代码里了。

package JUC;import java.util.concurrent.*;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.locks.ReentrantLock;/** * 判断公平锁和非公平锁的依据是模拟了thread2和thread3会竞争锁资源,然后以sleep时间代表是thread2还是thread3 * thread2是sleep 250,thread3是sleep 200 * 公平锁的情况下,250一定在200前面;非公平锁的情况下会出现200在250的前面 * 非公平锁出现200在250之前的情况是因为thread3此时和AQS中thread2竞争,先拿到了锁,先输出了200 * 公平锁的情况下thread3不会和AQS中的thread2竞争,加在了thread2的后面,所以结果稳定是200在250的后面 * 使用sleep时间来表示thread2和thread3而不使用线程名的原因是:笔者使用的是线程池,线程池中的线程执行顺序和变量thread1、thread2、thread3没有关系,可能会出现线程3执行thread3,详细情况可以将第36行注释删除打印输出来看(可能需要多run几次或者修改59行的i的上限) * 第63行和第65行可以用于选择公平锁和非公平锁 * @author lvgang * @date 2021/4/15 15:51 */public class ReentrantLockTest {    static class TestThread implements Runnable {        ReentrantLock lock;        int sleepTime;        CountDownLatch latch3Thread;        TestThread(ReentrantLock lock, int sleepTime, CountDownLatch latch3Thread) {            this.lock = lock;            this.sleepTime = sleepTime;            this.latch3Thread = latch3Thread;        }        @Override        public void run() {            lock.lock();            try {                // System.out.println(Thread.currentThread().getName());                System.out.println("sleep时间:" + sleepTime);                Thread.sleep(sleepTime);            } catch (InterruptedException e) {                e.printStackTrace();            } finally {                lock.unlock();                latch3Thread.countDown();            }        }    }    public static void main(String[] args) throws InterruptedException {        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 6, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadFactory() {            private final AtomicInteger atomicInteger = new AtomicInteger(1);            @Override            public Thread newThread(Runnable r) {                return new Thread(r, "faceSchool线程_" + atomicInteger.getAndIncrement());            }        });        for (int i = 0; i < 20; i++) {            // latch3Thread的作用是让3个线程运行完之后再开始下一次公平锁或者非公平锁的结果的模拟,避免多次run,使得结果的对比不明显            CountDownLatch latch3Thread = new CountDownLatch(3);            // 非公平锁             ReentrantLock lock = new ReentrantLock();            // 公平锁            // ReentrantLock lock = new ReentrantLock(true);            TestThread thread1 = new TestThread(lock, 300,  latch3Thread);            threadPoolExecutor.execute(thread1);            // 此处的sleep是保证thread1获取了锁,避免和thread2竞争            Thread.sleep(100);            TestThread thread2 = new TestThread(lock, 250, latch3Thread);            threadPoolExecutor.execute(thread2);            // 此处的sleep是保证thread2进入了lock的AQS队列,顺便等待thread1运行完,模拟出thread2和thread3在非公平锁下的竞争情况            Thread.sleep(200);            TestThread thread3 = new TestThread(lock, 200, latch3Thread);            threadPoolExecutor.execute(thread3);            latch3Thread.await();            System.out.println("--------------------------------------------------------");        }        threadPoolExecutor.shutdown();    }}

    公平锁的结果:

    非公平锁的结果:

    笔者能力有限,有问题的地方,烦请指出。

   欢迎关注公众号:faceSchool。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值