`
jimichan
  • 浏览: 280354 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Concurrent In Java 6 分享,第三部分 锁

    博客分类:
  • java
阅读更多

第一部分 集合 http://jimichan.iteye.com/blog/951948

 

第二部分 线程池 http://jimichan.iteye.com/blog/951950

 

第三部分 锁 http://jimichan.iteye.com/blog/951954

 

第四部分 同步辅助类 http://jimichan.iteye.com/blog/951955

Concurrent In Java,第三部分 锁

 

2011-3-9  延昭 & 陈汝烨 版权所有,特别禁止发布到百度文库

这篇是来自公司内部分享会议是写的总结,有些内容没有表达出来,大家可以来踩,但是需留下原因,以便后续补充。

3. java.util.concurrent.locks

 

java 早期内置synchronized关键字解决多线程对共享资源访问的一些问题,和其还配套了Object的notify 和 wait方法,用来控制线程之间的同步。

 

concurrent软件包提供了更为高级和抽象的Lock工具,能解决更多的问题。

 

Lock是控制多个线程对共享资源进行访问的工具。通常Lock限定多线程对同一个共享资源访问的限制,一次只允许一个线程获得Lock,即获得对共享资源的访问权限,线程间是互斥的。但是也有一些锁如果ReadWriteLock是允许部分线程同时访问共享资源的。

 

 

几个术语:

 

争用:当多个Thread在同一时间内(相对概念)想要占有同一个Lock对象。那么JVM会调度解决争用。

 

获取顺序:当多个线程争用同一个Lock对象,那么JVM就要决定哪个线程将会获得锁权限。存在两种模式:公平不公平。 默认都是不公平模式,包括synchronized关键字,jvm决定顺序的时候也是采用不公平策略。因为公平策略需要系统记录大量辅助信息来判断分配顺序,而不公平策略由JVM决定一直快速高效的算法来分配Lock。所以不公平策略的系统吞吐量会比较高(花费更少的空间和计算在分配上),如果没有特殊需要则默认采用不公平策略。

 

重入:当前线程获取指定的锁对象权限后,还可以再次获取该锁。Lock内部会有一个计数器来表明当前线程获取了该锁的数量。如果一个线程获取了一个锁两次,那么线程必须释放锁两次,才能被看作完全释放了该锁,所以编程的时候一定要注意使用重入。synchronized关键字也是支持重入语义的。

3.1 Lock & ReentrantLock

ReentrantLock实现了Lock接口,一个可重入(reentrant)的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

 

摘自JavaDoc的一段获取规则 “当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。”

 

经典使用方法。

public void m() { 
    lock.lock();  // block until condition holds
    try {
      // ... method body
    } finally {
      lock.unlock()
    }
  }

 

 

ReentrantLock除了实现了Lock规定的方法外,还实现了tryLock、isLocked 等方法,帮助你实现更多的场景。

 

Condition

和Object的wait和notify方法类似。ReentrantLock对象附加了Conditon对象,用来完成挂起和唤醒操作,使用lock.newCondition() 方法生成。

一个来自JKD的例子:

class BoundedBuffer {
  
final Lock lock = new ReentrantLock();
  final Condition notFull  = 
lock.newCondition(); 
  final Condition notEmpty = 
lock.newCondition(); 

  final Object[] items = new Object[100];
  int putptr, takeptr, count;

  public void put(Object x) throws InterruptedException {
    
lock.lock();
    try {

      while (count == items.length) 
        
notFull.await();
      items[putptr] = x; 
      if (++putptr == items.length) putptr = 0;
      ++count;
      
notEmpty.signal();
    
} finally {
      lock.unlock();
    }

  }

  public Object take() throws InterruptedException {
    
lock.lock();
    try {

      while (count == 0) 
        
notEmpty.await();
      Object x = items[takeptr]; 
      if (++takeptr == items.length) takeptr = 0;
      --count;
      
notFull.signal();
      return x;
    
} finally {
      lock.unlock();
    }

  } 
}

 

利用Conditon对象可以让所有对同一个锁对象进行争用的Thread之间进行同步。

 

 

Lock VS synchronized

除非你有明确的需求或者并发遇到瓶颈的时候再决定使用ReentrantLock。synchronized在大部分时候还是可以工作的很好,jvm会自动处理和回收锁。

 

ReentrantLock提供了更多的选择和状态信息。和

 

 

3.2 ReadWriteLock & ReentrantReadWriteLock

列举一个场景对象X,拥有方法a、b、c。a和b方法不改表X的内部状态,c改变内部状态。在多线程环境下,我们要求只读和写(变更状态)是不能同时进行的,而只读操作是可以同时并发的,且实际运行过程中读操作数量远远大于写操作的数量。

 

如果用synchronized关键字的话,两个只读方法a、b也会互斥,并发性能收到限制。

 

那么这个情况下ReadWriteLock就非常有用,使用也非常简单。

 

class RWDictionary {
   private final Map<String, Data> m = new TreeMap<String, Data>();
   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
   private final Lock r = rwl.readLock();
   private final Lock w = rwl.writeLock();

   public Data get(String key) {
       r.lock();
       try { return m.get(key); }
       finally { r.unlock(); }
   }
   public String[] allKeys() {
       r.lock();
       try { return m.keySet().toArray(); }
       finally { r.unlock(); }
   }
   public Data put(String key, Data value) {
       w.lock();
       try { return m.put(key, value); }
       finally { w.unlock(); }
   }
   public void clear() {
       w.lock();
       try { m.clear(); }
       finally { w.unlock(); }
   }
}

 

 

要记得write锁是独占的,它一样可以使用ReentrantLock的Condition功能。

 

使用任何的锁都要通过try catch 或者 finally 来处理异常,避免忘记unlock。

 

 

第四部分 同步辅助类

http://jimichan.iteye.com/blog/951955

 

 

2
6
分享到:
评论

相关推荐

    Concurrent - Programming in Java.pdf

    - **第三方库**:例如Apache Commons Concurrency等。 ##### 2. 构建库 - **自定义并发组件**:根据项目需求开发特定的并发工具。 - **文档编写**:为自定义组件编写详细的文档,方便其他开发者理解和使用。 #### ...

    word版本

    《Java并发编程实践》第二版是一本专注于Java编程语言中并发程序设计的著作,由Doug Lea撰写,Addison Wesley出版社于1999年10月出版。这本书旨在为那些熟悉面向对象编程但对并发编程了解不多的开发者提供指导,同时...

    Java并发编程:设计原则与模式(Concurrent.Programming.in.Java)(中英版)

    《Java并发编程:设计原则与模式》是一本深入探讨Java多线程编程的权威书籍,由Doug Lea撰写,第二版全面涵盖了Java并发处理的各个方面。这本书不仅提供了丰富的理论知识,还介绍了实战中的设计原则和模式,对于Java...

    Concurrent Programming in Java

    《Concurrent Programming in Java》第二版是一本非常有价值的参考书,适合希望深入了解Java并发编程的开发人员。通过本书的学习,读者不仅可以掌握Java提供的强大并发工具,还能学会如何设计健壮、高效的并发程序。...

    Concurrent.Programming.in.Java - Design.Principles.and.Patterns(Second.Edition)

    # 并发编程在Java中的应用:设计原则与模式(第二版) ## 一、并发对象导向编程概览 ### 1.1 引言 本书《Concurrent Programming in Java - Design Principles and Patterns (Second Edition)》深入探讨了在Java...

    Concurrent_Programming+Java Concurrency in Practice+langspec

    其次,"langspec-3.0.pdf"可能指的是Java语言规范第三版,这是Java开发者的重要参考资料。这个文档详细定义了Java语言的所有语法、语义和行为,包括并发部分。在Java语言规范中,你会找到关于线程、对象的内存模型、...

    1999+-+Concurrent+Programming+in+Java[1].+Design+Principles+and+Pattern+2nd-ed+-+Doug+Lea.rar

    3. **同步机制**:详述了synchronized关键字、volatile变量、wait/notify机制、java.util.concurrent库(如Semaphore、CyclicBarrier、ExecutorService等)的使用及其背后的原理。 4. **并发工具类**:深入分析了...

    Thinking in java 4th 源代码

    《Thinking in Java》是Bruce Eckel的经典编程教材,第四版更是深受广大Java程序员喜爱。这本书深入浅出地讲解了Java语言的核心概念和技术,是学习Java的宝贵资源。源代码是理解书中理论的最佳实践,通过阅读和运行...

    [Thinking In Java 练习题答案 第四版]Annotated+Solution+Guide+for+TIJ4.rar

    6. **多线程**:Java提供了强大的多线程支持,书中会讲解线程的创建、同步、互斥等概念,以及synchronized关键字和java.util.concurrent包中的高级工具。 7. **泛型**:泛型是Java 5引入的新特性,用于提高代码的...

    Thinking in Java 3th and 4th Edition+代码+答案

    第三版是针对Java 2 Platform Standard Edition (J2SE) 1.4编写的,该版本的Java引入了许多新特性,如泛型(Generics)、枚举类型(Enums)、可变参数(Varargs)以及集合框架的改进等。在这一版中,你可以学习到: ...

    Java Concurrency in Practice中文版

    3. **第三章:同步基础** - 深入讨论synchronized关键字的用法,包括锁的概念、可重入性以及监视器对象的使用。 4. **第四章:细粒度同步** - 探讨如何使用更细粒度的锁来提高并发性能,包括读写锁、Condition接口...

    JAVA_API1.6文档(中文)

    javax.sql.rowset.spi 第三方供应商在其同步提供者的实现中必须使用的标准类和接口。 javax.swing 提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所有平台上的工作方式都相同。 javax.swing....

    Learning Concurrent Programming in Scala

    - **异步库扩展**:除了标准库提供的Futures外,还有许多第三方库扩展了Scala的异步编程能力,如Akka Future等。 #### 八、数据并行集合 - **Scala集合概述**:Scala提供了一套丰富的集合框架,支持各种不同的集合...

    java_concurrency_in_practice

    - **第3章:对象共享** 这一章节详细探讨了可见性问题,并分析了对象的发布与逃逸现象。此外还提到了线程限制、不可变性以及安全发布等关键概念。 - **第4章:对象组合** 讨论了设计线程安全类的方法,比如实例...

    Concurrent+Programming+in+Java+-+Design+Principles+and+Patterns,+Second+Edition_

    第三章重点关注状态依赖性在并发编程中的应用。这一章探讨了如何管理和控制对象状态的变化,以确保在并发环境下的正确性和一致性。 ##### 3.1 处理失败 本节讨论了如何在并发环境中处理异常和失败情况。这包括如何...

    thinking in java 英文版

    该压缩包文件包含的书籍可能是《Thinking in Java》的第三版。这一版在当时已经涵盖了Java的许多重要特性,包括基础语法、类和对象、接口、继承、多态、异常处理、容器、集合框架、网络编程、I/O流、并发处理以及...

    Thinking inJAVA原代碼

    6. **多线程**:Java提供了丰富的多线程支持,包括Thread类、Runnable接口和并发包(java.util.concurrent)。多线程编程涉及同步、互斥、线程池等概念,是高并发场景下的必备知识。 7. **输入/输出流**:Java的I/O...

    think in java4 中文版(真正的第四版)

    在中文版的《Think in Java第四版》中,读者可以全面了解Java编程的基础知识,包括但不限于: 1. **基础语法**:学习Java的基本数据类型、变量、常量、运算符以及流程控制语句,如if-else、switch、for、while等,...

    Java 1.6 API 中文 New

    javax.sql.rowset.spi 第三方供应商在其同步提供者的实现中必须使用的标准类和接口。 javax.swing 提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所有平台上的工作方式都相同。 javax.swing.border ...

Global site tag (gtag.js) - Google Analytics