您当前的位置: 首页 >  Java

小志的博客

暂无认证

  • 3浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java并发多线程编程——公平锁和非公平锁的理解、源码解析和案例

小志的博客 发布时间:2021-04-25 21:53:24 ,浏览量:3

目录
    • 一、公平锁与非公平锁的理解
    • 二、公平锁与非公平锁的优缺点
    • 三、公平锁与非公平锁的创建方式
    • 三、ReentrantLock类中实现公平锁部分源码
    • 四、ReentrantLock类中实现非公平锁部分源码
    • 五、公平锁代码示例
    • 五、非公平锁代码示例

一、公平锁与非公平锁的理解
  • 公平锁:表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序
  • 非公平锁:一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。
二、公平锁与非公平锁的优缺点

1、公平锁

  • 优点:所有的线程都能得到资源,不会饿死在队列中。
  • 缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。

2、非公平锁

  • 优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。
  • 缺点:可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。
三、公平锁与非公平锁的创建方式
  • 创建一个非公平锁(默认是非公平锁)

    //创建非公平锁方式一
    Lock lock = new ReentrantLock();
    //创建非公平锁方式二
    Lock lock = new ReentrantLock(false);
    
  • 创建一个公平锁

    //创建公平锁,构造传参true
    Lock lock = new ReentrantLock(true);
    
  • 源码截图 在这里插入图片描述

三、ReentrantLock类中实现公平锁部分源码

1、FairSync 公平锁源码

 	 /**
     * 公平锁的同步对象
     */
 	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){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count --;
                System.out.println(Thread.currentThread().getName() + "卖票成功,余票为:" + count);
            }
            reentrantLock.unlock();
        }

    }

    public static void main(String[] args) {
        Demo2 d=new Demo2();

        //第1个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();

        //第2个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();

        //第3个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();
    }
}

2、输出结果 在这里插入图片描述

五、非公平锁代码示例

1、代码

package com.xz.thread.t10;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description: 非公平锁示例代码
 * @author: xz
 */
public class Demo {
    //总票数
    private int count =10;

    //创建锁 ReentrantLock可实现公平锁与非公平锁
    private Lock reentrantLock = new ReentrantLock();

    //获取余票数量方法
    public void getCount(){
        while (true){
            //锁住
            reentrantLock.lock();
            if (count > 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count --;
                System.out.println(Thread.currentThread().getName() + "卖票成功,余票为:" + count);
            }
            reentrantLock.unlock();
        }

    }

    public static void main(String[] args) {
        Demo d=new Demo();

        //第1个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();

        //第2个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();

        //第3个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                d.getCount();
            }
        }).start();
    }
}

2、输出结果 在这里插入图片描述

关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.0432s