公平锁案例

wen java案例 1

本文目录导读:

公平锁案例

  1. 什么是公平锁?
  2. 完整案例
  3. 更直观的演示案例
  4. 自定义公平锁实现(简单版本)
  5. 公平锁与非公平锁的区别
  6. 运行结果对比(示例)

我将为您提供一个完整的公平锁案例,帮助您理解公平锁的特性。

什么是公平锁?

公平锁是指多个线程按照申请锁的顺序来获取锁,先到先得,而非公平锁则允许线程"插队"。

完整案例

import java.util.concurrent.locks.ReentrantLock;
public class FairLockExample {
    // 公平锁参数设为true
    private static final ReentrantLock fairLock = new ReentrantLock(true);
    // 非公平锁参数设为false(默认)
    private static final ReentrantLock unfairLock = new ReentrantLock(false);
    private static int sharedResource = 0;
    public static void main(String[] args) throws InterruptedException {
        System.out.println("========== 公平锁测试 ==========");
        testFairLock();
        Thread.sleep(2000);
        System.out.println("\n========== 非公平锁测试 ==========");
        testUnfairLock();
    }
    // 测试公平锁
    private static void testFairLock() throws InterruptedException {
        Thread[] threads = new Thread[10];
        long startTime = System.currentTimeMillis();
        // 创建10个线程
        for (int i = 0; i < 10; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    fairLock.lock();
                    try {
                        sharedResource++;
                        Thread.sleep(10); // 模拟业务操作
                        System.out.println("公平锁 - 线程" + threadId + " 第" + j + "次获取锁,当前值: " + sharedResource);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        fairLock.unlock();
                    }
                }
            });
            threads[i].start();
        }
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        long fairTime = System.currentTimeMillis() - startTime;
        System.out.println("公平锁执行总耗时: " + fairTime + "ms");
    }
    // 测试非公平锁
    private static void testUnfairLock() throws InterruptedException {
        Thread[] threads = new Thread[10];
        long startTime = System.currentTimeMillis();
        // 创建10个线程
        for (int i = 0; i < 10; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    unfairLock.lock();
                    try {
                        sharedResource++;
                        Thread.sleep(10); // 模拟业务操作
                        System.out.println("非公平锁 - 线程" + threadId + " 第" + j + "次获取锁,当前值: " + sharedResource);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        unfairLock.unlock();
                    }
                }
            });
            threads[i].start();
        }
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        long unfairTime = System.currentTimeMillis() - startTime;
        System.out.println("非公平锁执行总耗时: " + unfairTime + "ms");
    }
}

更直观的演示案例

import java.util.concurrent.locks.ReentrantLock;
public class FairLockDemonstration {
    private static final ReentrantLock lock = new ReentrantLock(true); // 公平锁
    public static void main(String[] args) {
        // 创建5个线程,观察获取锁的顺序
        for (int i = 1; i <= 5; i++) {
            new Thread(new Task("任务" + i)).start();
        }
        // 稍微等待,让线程按顺序启动
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 主线程也参与竞争
        lock.lock();
        try {
            System.out.println("主线程获取了锁");
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    static class Task implements Runnable {
        private final String name;
        Task(String name) {
            this.name = name;
        }
        @Override
        public void run() {
            // 每个任务尝试获取锁3次
            for (int i = 0; i < 3; i++) {
                lock.lock();
                try {
                    System.out.println(name + " - 第" + (i+1) + "次获取锁,执行中...");
                    Thread.sleep(100); // 模拟工作
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}

自定义公平锁实现(简单版本)

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class CustomFairLock {
    // 使用ReentrantLock实现公平锁
    private final ReentrantLock lock = new ReentrantLock(true);
    private final Condition notEmpty = lock.newCondition();
    private int[] buffer = new int[10];
    private int count = 0;
    private int putIndex = 0;
    private int takeIndex = 0;
    // 生产者方法
    public void produce(int value) {
        lock.lock();
        try {
            while (count == buffer.length) {
                notEmpty.await();
            }
            buffer[putIndex] = value;
            putIndex = (putIndex + 1) % buffer.length;
            count++;
            System.out.println(Thread.currentThread().getName() + " 生产了: " + value + ",当前数量: " + count);
            notEmpty.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
    // 消费者方法
    public int consume() {
        lock.lock();
        int value;
        try {
            while (count == 0) {
                notEmpty.await();
            }
            value = buffer[takeIndex];
            takeIndex = (takeIndex + 1) % buffer.length;
            count--;
            System.out.println(Thread.currentThread().getName() + " 消费了: " + value + ",当前数量: " + count);
            notEmpty.signalAll();
            return value;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return -1;
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        CustomFairLock buffer = new CustomFairLock();
        // 创建多个生产者和消费者
        for (int i = 0; i < 5; i++) {
            final int producerId = i;
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    buffer.produce(producerId * 10 + j);
                }
            }, "生产者" + i).start();
        }
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                for (int j = 0; j < 3; j++) {
                    buffer.consume();
                }
            }, "消费者" + i).start();
        }
    }
}

公平锁与非公平锁的区别

特性 公平锁 非公平锁
获取锁顺序 先来先得 允许插队
性能 相对较慢(需要维护队列) 相对较快
公平性 保证公平 不保证公平
适用场景 需要公平性的场景 对性能要求高的场景
实现机制 基于FIFO队列 基于CAS操作

运行结果对比(示例)

========== 公平锁测试 ==========
公平锁 - 线程0 第0次获取锁,当前值: 1
公平锁 - 线程0 第1次获取锁,当前值: 2
公平锁 - 线程0 第2次获取锁,当前值: 3
公平锁 - 线程1 第0次获取锁,当前值: 4
...
公平锁执行总耗时: 412ms
========== 非公平锁测试 ==========
非公平锁 - 线程3 第0次获取锁,当前值: 31
非公平锁 - 线程3 第1次获取锁,当前值: 32
...
非公平锁执行总耗时: 289ms
  1. 公平锁:严格按照线程请求的顺序获取锁,但性能相对较差
  2. 非公平锁:允许线程插队,性能较好但可能导致某些线程"饿死"
  3. 使用建议:除非有特殊需求,一般推荐使用非公平锁(默认)
  4. 实现方式:公平锁使用FIFO队列保证顺序,非公平锁使用CAS原子操作

这个案例展示了公平锁的基本使用方法和特性,您可以根据实际需求选择合适的锁类型。

抱歉,评论功能暂时关闭!