`

并发专题 --- 锁

 
阅读更多
相比于synchronized,ReentrantLock 提供了更多的灵活性来处理不可用的锁。下面具体来介绍一下ReentrantLock 的使用。

1.  实现可轮询的锁请求
在内部锁中,死锁是致命的——唯一的恢复方法是重新启动程序,唯一的预防方法是在构建程序时不要出错。而可轮询的锁获取模式具有更完善的错误恢复机制,可以规避死锁的发生。
如果你不能获得所有需要的锁,那么使用可轮询的获取方式使你能够重新拿到控制权,它会释放你已经获得的这些锁,然后再重新尝试。可轮询的锁获取模式,由tryLock()方法实现。此方法仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值true。如果锁不可用,则此方法将立即返回值false。此方法的典型使用语句如下:
    
 Lock lock = ...; 
      if (lock.tryLock()) { 
          try { 
              // manipulate protected st
          } finally { 
              lock.unlock(); 
          } 
      } else { 
          // perform alternative actions 
      } 


2.  实现可定时的锁请求
当使用内部锁时,一旦开始请求,锁就不能停止了,所以内部锁给实现具有时限的活动带来了风险。为了解决这一问题,可以使用定时锁。当具有时限的活动调用了阻塞方法,定时锁能够在时间预算内设定相应的超时。如果活动在期待的时间内没能获得结果,定时锁能使程序提前返回。可定时的锁获取模式,由tryLock(long, TimeUnit)方法实现。


3.  实现可中断的锁获取请求
可中断的锁获取操作允许在线程可取消(cancel)的活动中使用。lockInterruptibly()方法能够使你获得锁的时候响应中断。

总之,ReentrantLock 锁与Java 内在锁相比有下面的特点:
1)ReentrantLock 必须在 finally  块中释放锁,而使用synchronized 同步,JVM 将确保锁会获得自动释放。
2)与目前的 synchronized  实现相比,争用下的 ReentrantLock  实现更具可伸缩性。
3)对于ReentrantLock  ,可以有不止一个条件变量与它关联。
4)允许选择想要一个公平锁,还是一个不公平锁。
5)除非您对 Lock  的某个高级特性有明确的需要,或者有明确的证据表明在特定情况下,同步已经成为可伸缩性的瓶颈     否则还是应当继续使用 synchronized。
6)Lock  类只是普通的类,JVM  不知道具体哪个线程拥有 Lock  对象。而且,几乎每个开发人员都熟悉 synchronized     它可以在 JVM  的所有版本中工作。

--------------------------------------------
读-写锁
---------
读-写锁允许的情况是:一个资源能够被多个读线程访问,或者被一个写线程访问,但两者不能同时进行。
读-写锁的定义如表所示:
public interface ReadWriteLock{ 
    Lock readLock();//返回用于读取操作的锁 
    Lock writeLock();//返回用于写入操作的锁。 
}
。。。。
 //  读写锁 
  private final ReadWriteLock lock = new ReentrantReadWriteLock(); 
  private final Lock readLock = lock.readLock(); //  读锁 
  private final Lock writeLock = lock.writeLock(); //  写锁
。。。。

ReadWriteLock  维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader  线程同时保持。写入锁是独占的。
===========================================================================
锁的劣势
-----------
1. 多个线程调度开销
如果有多个线程同时请求锁,一些线程将可能被挂起,并稍后恢复运行。从线程开始恢复,到它真正被调度前,可能必须等待其他线程完成它们的调度限额规定的时问。挂起和恢复线程会带来很大的开销,并通常伴有冗长的中断。对于基于锁,并且其操作过度细分的类(比如同步容器类,大多数方法只包含很少的操作),当频繁地发生锁的竞争时,调度与真正用于工作的开销间的比值会很可观。

2.优先级倒置(priority inversion),无限循环、死锁、活锁和其他活跃度失败

------------------------------------------------------------------------
原子变量类
-----------
java.util.concurrent.atomic  包中添加原子变量类。所有原子变量类都公开“比较并设置”原语(与比较并交换类似),这些原语都是使用平台上可用的最快本机结构(比较并交换、加载链接/条件存储,最坏的情况下是旋转锁)来实现的。

原子变量类共有12 个,分成4 组:计量器、域更新器(field updater)、数组以及复合变量。最常用的原子变量是计量器:AtomicInteger、AtomicLong、AtomicBoolean 以及 AtomicReference。他们都支持 CAS ,AtomicInteger 和AtomicLong 还支持算术运算。

调整具有竞争的并发应用程序的可伸缩性的通用技术是降低使用的“锁对象的粒度”,希望更多的锁请求从竞争变为不竞争。从锁转换为原子变量可以获得相同的结果,通过切换为更细粒度的协调机制,竞争的操作就更少,从而提高了吞吐量。

--------------------------------------------------------------------------
非阻塞算法
------------
一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法被称为非阻塞(non-blocking)算法。
如果算法的每一步骤中都有一些线程能够继续执行,那么这样的算法称为无锁(lock-free)算法。

非阻塞算法对死锁和优先级倒置有“免疫性”。好的非阻塞算法已经应用到多种常见的数据结构上,包括栈、队列、优先级队列、哈希表。

非阻塞算法相对于基于锁的算法有几个性能优势。
首先,它用硬件的原生形态代替 Java 虚拟机的锁定代码路径,从而在更细的粒度层次上(独立的内存位置)进行同步,失败的线程也可以立即重试,而不会被挂起后重新调度。更细的粒度降低了争用的机会,不用重新调度就能重试的能力也降低了争用的成本。即使有少量失败的CAS 操作,这种方法仍然会比由于锁竞争造成的重新调度快得多。

如果深入 Java 虚拟机和操作系统,会发现非阻塞算法无处不在。垃圾收集器使用非阻塞算法加快并发和平行的垃圾搜集;调度器使用非阻塞算法有效地调度线程和进程,实现内在锁。
分享到:
评论

相关推荐

    面试专题--并发篇代码

    本专题将重点探讨这些核心概念及其在实际开发中的应用。 首先,我们来了解什么是并发。并发是指在同一时间段内,多个任务看似同时进行的状态。在单核CPU系统中,这通常是通过时间片轮转实现的,而在多核系统中,...

    面试必问并发编程高级面试专题-09.rar

    本专题针对的是高级面试中的并发编程问题,旨在帮助求职者深入理解并发概念,掌握核心技术和解决策略。 首先,我们需要理解并发编程的基础概念。并发是指在一段时间内,多个任务看似同时执行的状态。这种现象可以...

    面试专题-面试人员必看-并发面试专题1.pdf

    Java并发编程是Java高级开发人员面试中的一个重要议题,其中对Synchronized关键字的理解和使用又是并发面试中的核心问题之一。Synchronized关键字是Java提供的原生同步机制,用于控制多线程对共享资源的互斥访问。...

    MYSQL专题-查询优化-使用索引-安全隐患-事务与锁.docx

    事务和锁是数据库并发控制的重要手段,事务可以保证数据的一致性和完整性,而锁可以防止并发访问的冲突。需要正确地使用事务和锁,以避免数据的不一致和丢失。 数据库查询优化是一个复杂的过程,需要从多个方面进行...

    面试专题-并发篇讲义.pdf

    【并发编程】是Java开发中的重要领域,面试中经常被问到。理解并掌握线程的状态转换对于理解和解决并发问题至关重要。Java线程有六种状态:新建、可运行、运行、阻塞、等待和终结。 1. **新建**:线程对象创建但...

    并发面试专题.pdf

    ### 并发面试专题知识点详解 #### 一、Synchronized的基本概念及原理 **Synchronized** 是Java语言中用于实现线程同步的关键字之一。它主要用于控制多个线程对共享资源的访问,确保同一时刻只有一个线程能够访问...

    面试真题包含spring-java-集合-框架-并发-spring-运维-数据库等多领域45卷合集.rar

    在并发领域,"并发面试专题.pdf"可能会包含线程安全、锁机制、并发工具类如Semaphore、CountDownLatch和CyclicBarrier,以及Java内存模型(JMM)等内容。求职者需要了解如何避免死锁,掌握线程池的工作原理,以及...

    Java面试专题-面试人员必看-微服务架构面试专题系列:Tomcat+Mysql+设计模式+并发+Netty+JVM.rar

    本面试专题涵盖了微服务架构中的关键组件,包括Tomcat、Mysql、设计模式、并发处理、Netty以及JVM。以下是这些主题的详细说明: 1. **Tomcat**:作为Java Servlet容器,Tomcat是Web应用程序的基础。了解其工作原理...

    并发专题.zip

    在这个“并发专题.zip”压缩包中,我们可以期待找到一系列关于并发编程的知识点和资源。 并发编程的核心概念包括线程、进程、同步与互斥、死锁、活锁以及饥饿等。下面我们将详细讨论这些关键概念。 1. **线程与...

    图灵Java高级互联网架构师第6期并发编程专题笔记.zip

    07-并发锁机制之深入理解synchronized(一)-fox 08-并发锁机制之深入理解synchronized(二)-fox 09-深入理解AQS之独占锁ReentrantLock源码分析-fox 10-深入理解AQS之Semaphorer&CountDownLatch&CyclicBarrie详解-...

    oracle数据库闩锁锁定与并发专题.doc

    在这个专题中,我们主要探讨的是Oracle数据库中的闩锁(Latch)和锁定(Lock)机制,这两种机制都是为了实现并发操作的串行化,防止数据的破坏。 首先,串行化是数据库管理系统中确保数据安全的重要原则,即使在多...

    面试必问并发编程高级面试专题.zip

    本面试专题主要针对高级并发编程的知识点进行探讨,旨在帮助求职者在面试中展现出深厚的并发编程理论基础和实践经验。 1. **线程与进程** - **线程定义**:线程是操作系统分配处理器时间的基本单位,它是进程中...

    并发编程面试专题.pdf

    ### 并发编程面试专题知识点解析 #### 一、线程执行顺序控制 **知识点:** 1. **问题描述:** 如何确保线程T2在T1执行完毕后开始执行,T3在T2执行完毕后开始执行? 2. **解决方案:** 可以通过`Thread.join()`方法...

    高并发多线程面试专题及答案(上).pdf

    关于Java中的高并发和多线程面试专题,以下是详细的知识点: 1. Synchronized的使用和原理 Synchronized是Java中的一个关键字,用于实现线程间的同步。它是由JVM实现的一种控制线程访问共享资源的机制。当一个方法...

    JavaSE专题-多线程总结.doc

    JavaSE专题的多线程是Java编程中至关重要的一部分,它涉及到如何在单个程序中同时执行多个任务。以下是对多线程技术的详细说明: 1. **多线程技术介绍** - **进程**:一个进程是操作系统分配给应用程序的内存空间...

    Python并发编程专题.zip

    本专题将深入探讨Python中的并发模型、线程与进程、异步I/O以及相关库的使用。 1. **Python并发模型** Python提供了多种并发模型,包括多线程(threads)、多进程(processes)以及基于协程(coroutines)的异步...

    java并发编程专题(五)----详解(JUC)ReentrantLock

    Java并发编程中的ReentrantLock是Java并发包(java.util.concurrent,简称JUC)中的一个重要的锁机制,它是Lock接口的一个具体实现,提供了比synchronized更强大的锁定功能和更细粒度的控制。ReentrantLock的主要...

    多线程面试专题-答案.pdf

    Lock可以提供读写锁,即读锁可以被多个线程共享,而写锁是排他锁。这样的机制特别适合实现类似ConcurrentHashMap这样的高效并发数据结构。在构建电子交易系统的客户端缓存和交易连接空间时,Lock接口也常常被使用。 ...

Global site tag (gtag.js) - Google Analytics