• 第六章:(2)公平锁与非公平锁


    一、案例

      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 类型的有参构造器,那么这两个有什么区别呢?

      使用无参构造器运行:

      

       使用有参构造器:

    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

     

     
  • 相关阅读:
    自动化测试初介
    接口测试初介
    常见测试面试过程及及问题解析
    hadoop伪分布式平台组件搭建
    使用Github搭建个人博客
    centos7中redis安装配置
    Hive安装配置
    hadoop大数据组件启动
    Java生成窗口
    正则语法
  • 原文地址:https://www.cnblogs.com/niujifei/p/15834253.html
Copyright © 2020-2023  润新知