2.5.线程的同步和协作_锁的公平性



锁的公平性

将Lock引入Java中的同时也增加锁的一个概念:公平性。在ReentrantLock和ReentrantReadWriteLock的构造函数中可以指定锁的公平性。

如果给构造函数传入false表明锁是非公平锁,在非公平锁中,当有很多线程在等待锁时,锁会随机选择其中一个来访问临界区,这个随机的选择没有任何约束。如果给构造函数传入true表明锁是公平锁,在公平锁中,当有很多线程等待锁时,锁会选择等待时间最长的来访问临界区。这种情况发生在Lock对象的lock和unlock方法。


synchronized关键字是一个非公平锁。非公平锁虽然是随机选择的,但从统计来看每个线程都会被激活,大部分的场景都适合非公平锁。另外,非公平锁的效率要比公平锁的效率高很多。


下面的示例说明了公平锁的运行机制,示例中会启动10个线程,每隔0.01秒启动一个,这样线程0-9的等待时间依次递减,从运行日志中可以看出:锁一定会选择等待时间最长的线程。


public class FireLockDemo {
    public static void main(String[] args){
        FireLockWorker worker = new FireLockWorker();
        Thread[] threads = new Thread[10];

        System.out.println("main:创建10个线程");
        for(int i=0 ;i<threads.length; i++){
            threads[i]  = new Thread(worker);
        }

        System.out.println("main:依次启动10个线程,每个线程之间间隔0.1秒");
        for(int i=0 ;i<threads.length; i++){
            threads[i].start();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class FireLockWorker implements Runnable{
    private Lock lock = new ReentrantLock(true);

    @Override
    public void run() {
        //等待其他线程启动
        lock.lock();
        long duration = (long)(Math.random()*1000);
        try{
            Thread.sleep(duration);
            System.out.println(Thread.currentThread().getName() +":等待其他线程启动");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{
            lock.unlock();
        }

        System.out.println(Thread.currentThread().getName() +":申请加锁");
        //模拟处理
        lock.lock();
        try{
            Thread.sleep(duration);
            System.out.println(Thread.currentThread().getName() +":操作完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{
            lock.unlock();
        }
    }
}

程序运行日志:

main:创建10个线程
main:依次启动10个线程,每个线程之间间隔0.1秒
Thread-0:等待其他线程启动
Thread-0:申请加锁
Thread-1:等待其他线程启动
Thread-1:申请加锁
Thread-2:等待其他线程启动
Thread-2:申请加锁
Thread-3:等待其他线程启动
Thread-3:申请加锁
Thread-4:等待其他线程启动
Thread-4:申请加锁
Thread-5:等待其他线程启动
Thread-5:申请加锁
Thread-6:等待其他线程启动
Thread-6:申请加锁
Thread-7:等待其他线程启动
Thread-7:申请加锁
Thread-8:等待其他线程启动
Thread-8:申请加锁
Thread-9:等待其他线程启动
Thread-9:申请加锁
Thread-0:操作完成
Thread-1:操作完成
Thread-2:操作完成
Thread-3:操作完成
Thread-4:操作完成
Thread-5:操作完成
Thread-6:操作完成
Thread-7:操作完成
Thread-8:操作完成
Thread-9:操作完成

将锁改成非公平锁`private Lock lock = new ReentrantLock(false);`,再考察程序的运行日志:

main:创建10个线程
main:依次启动10个线程,每个线程之间间隔0.1秒
Thread-0:等待其他线程启动
Thread-0:申请加锁
Thread-1:等待其他线程启动
Thread-1:申请加锁
Thread-2:等待其他线程启动
Thread-2:申请加锁
Thread-3:等待其他线程启动
Thread-3:申请加锁
Thread-4:等待其他线程启动
Thread-4:申请加锁
Thread-5:等待其他线程启动
Thread-5:申请加锁
Thread-6:等待其他线程启动
Thread-6:申请加锁
Thread-7:等待其他线程启动
Thread-7:申请加锁
Thread-7:操作完成
Thread-8:等待其他线程启动
Thread-8:申请加锁
Thread-8:操作完成
Thread-9:等待其他线程启动
Thread-9:申请加锁
Thread-0:操作完成
Thread-1:操作完成
Thread-2:操作完成
Thread-3:操作完成
Thread-4:操作完成
Thread-5:操作完成
Thread-6:操作完成
Thread-9:操作完成


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值