悲观锁:认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁。
乐观锁:认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的 *** 作。(例如报错或者自动重试)。
乐观锁通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增 *** 作就通过CAS自旋实现的。
实现场景:
-
悲观锁适合写 *** 作多的场景,先加锁可以保证写 *** 作时数据正确。
-
乐观锁适合读 *** 作多的场景,不加锁的特点能够使其读 *** 作的性能大幅提升。
公平锁:多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。公平锁的优点是等待锁的线程不会饿死。缺点是整体吞吐效率相对非公平锁要低,等待队列中除第一个线程以外的所有线程都会阻塞,CPU唤醒阻塞线程的开销比非公平锁大。
非公平锁:多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以非公平锁有可能出现后申请锁的线程先获取锁的场景。非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程。缺点是处于等待队列中的线程可能会饿死,或者等很久才会获得锁。
(举例:
公平锁场景:排队去管理员处打水,新来的必须去后面排队。打水的一个人打水后,管理员允许 下 一个打水。否则不可以。
非公平锁:插队打水,在排队的过程中,如果新进来一个线程,可以插队打水。如果插队成功则 先打水,如果失败则去后面排队打水。)
受启发地址:java中的各种锁详细介绍 - JYRoy - 博客园
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)