简介
公平锁
公平锁的获取方式是按照线程的申请顺序来获取锁,即先到先得。当多个线程同时竞争一个公平锁时,会按照线程的先后顺序依次获取锁资源。这种方式可以保证所有线程公平地访问共享资源,避免饥饿现象的发生。
公平锁的实现通常会维护一个等待队列,记录等待锁的线程,当锁释放时,从等待队列中选择最先等待的线程来获取锁。
公平锁的优点是保证了资源的公平分配,所有线程都有机会获取锁,避免了某些线程长时间无法获取锁的情况。但是,公平锁的实现需要维护一个等待队列,增加了额外的开销,并且在高并发场景下可能降低系统的吞吐量。
非公平锁
非公平锁的获取方式是无序的,不考虑线程的申请顺序,当锁可用时,任何线程都有机会获取锁。如果有多个线程同时竞争一个非公平锁,可能会出现某些线程连续获取锁的情况,导致其他线程长时间无法获取锁。
非公平锁的实现通常会优先尝试获取锁,如果获取失败才会进入等待状态,不会先进入等待队列。
非公平锁的优点是在高并发场景下,由于减少了等待队列的操作,可以获得更好的性能。但是,非公平锁可能会导致某些线程长时间无法获取锁,出现线程饥饿现象。
执行流程
非公平锁的吞吐率(单位时间内成功获取锁的平均速率)要比公平锁高很多。
公平锁
获取锁时,先将线程自己添加到等待队列的队尾并休眠,当某线程用完锁之后,会去唤醒等待队列中队首的线程尝试去获取锁,锁的使用顺序也就是队列中的先后顺序,在整个过程中,线程会从运行状态切换到休眠状态,再从休眠状态恢复成运行状态,但线程每次休眠和恢复都需要从用户态转换成内核态,而这个状态的转换是比较慢的,所以公平锁的执行速度会比较慢。
非公平锁
当线程获取锁时,会先通过 CAS 尝试获取锁,如果获取成功就直接拥有锁,如果获取锁失败才会进入等待队列,等待下次尝试获取锁。这样做的好处是,获取锁不用遵循先到先得的规则,从而避免了线程休眠和恢复的操作,这样就加速了程序的执行效率。
优缺点分析
公平锁的优点是按序平均分配锁资源,不会出现线程饿死的情况,它的缺点是按序唤醒线程的开销大,执行性能不高。
非公平锁的优点是执行效率高,谁先获取到锁,锁就属于谁,不会“按资排辈”以及顺序唤醒,但缺点是资源分配随机性强,可能会出现线程饿死的情况。