随笔 - 1162  文章 - 0  评论 - 16  阅读 - 59万 

一、案例

  1、售票案例

复制代码
//第一步  创建资源类,定义属性和和操作方法
class LTicket {
    //票数量
    private int number = 30;

    //创建可重入锁
    private final ReentrantLock lock = new ReentrantLock();

    //卖票方法
    public void sale() {
        //上锁
        lock.lock();
        try {
            //判断是否有票
            if(number > 0) {
                System.out.println(Thread.currentThread().getName()+" :卖出"+(number--)+" 剩余:"+number);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        } finally {
            //锁【lock.lock】必须紧跟try代码块,且unlock要放到finally第一行。
            //解锁
            lock.unlock();
        }

    }
}

public class LSaleTicket {
    public static void main(String[] args) {
        LTicket ticket = new LTicket();
        //第二步 创建多个线程,调用资源类的操作方法
        //创建三个线程

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "BB").start();

        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.sale();
            }
        }, "CC").start();
    }
}
复制代码

  在之前的售票案例中使用到了 ReentrantLock,使用的是无参的构造器,也就是非公平锁,其实还有一个支持 boolean 类型的有参构造器,那么这两个有什么区别呢?

  使用无参构造器运行:

  

 

   使用有参构造器:

1
private final ReentrantLock lock = new ReentrantLock(true);

 

  运行结果:

  

 

   可以发现当使用了无参构造器,创建的是非公平锁,也就是会随机安排给空闲的线程来执行。

  使用了公平锁,会按照一定的顺序来执行。

  2、相关源码

  ReentrantLock 构造器:

复制代码
    /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() {
        sync = new NonfairSync(); //默认非公平锁
    }

    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync(); //根据参数创建那种锁
    }
复制代码

  公平锁:FairSync

复制代码
    /**
     * Sync object for fair locks
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        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;
        }
    }
复制代码

 

  非公平锁:NonFairSync

复制代码
    /**
     * Sync object for non-fair locks
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
复制代码

 

  3、公平锁与非公平锁

  非公平锁:可能会发生线程饿死,但是执行效率高(默认是非公平锁)

  公平锁:选用空闲的线程来执行,阳光普照,但是效率相对低;

 

二、公平锁与非公平锁

  深入学习参考:

  1、https://zhuanlan.zhihu.com/p/115543000

  2、https://www.cnblogs.com/heyouxin/p/13037146.html

 

 

 
posted on   格物致知_Tony  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
点击右上角即可分享
微信分享提示

目录导航