1.java.util.concurrent

线程同步:

  • 是因为多线程读写竞争资源需要同步
  • Java语言提供了synchronized/wait/notify来实现同步
  • 编写多线程同步很困难

所以Java提供了更高级的java.util.concurrent包:

  • 更高级的同步功能
  • 简化多线程程序的编写
  • JDK>= 1.5

2.ReetrantLock

java.util.locks.ReentrantLock用于替代synchronized加锁

synchronized是Java语言层面提供的,不需考虑异常

ReentrantLock是普通的Java类,要用try...finally来保证锁能够正确释放



当我们使用ReenTrantLock的时候,我们首先要通过new ReentrantLock()新建一个Lock对象。然后我们先试图用lock()方法获得当前对象的锁。如果我们获得锁成功,就进入try代码,最后在finally中用unlock()来释放这个锁。

注意:lock()方法必须在try代码之外完成。因为lock()可能会失败,而unlock()一定要在finally中完成。

class Count{
final Lock lock = new ReetrantLock(); //获得ReentrantLock对象
public void inc(){
lock.lock(); //获得当前对象的锁可能会失败,所以要放在try...finally外面
try{
n = n + 1;
}finally{
lock.unlock(); //释放锁
}
}

ReentrantLock:

  • 可重入锁,一个线程可多次获取同一个锁
  • lock()方法可获取锁
  • tryLock()方法可尝试获取锁并可指定超时。
class Counter{
final Lock lock = new ReentrantLock();
private void inc() throws InterruptedException{
if(lock.tryLock(1, TimeUnit.SECONDS)){
try{
n = n + 1;
}finally {
lock.unlock();
}
}
}
}

使用ReentrantLock比直接使用synchronized更安全,因为synchronized会导致线程要么获得锁,要的永远等待下去。而使用ReentrantLock的时候,我们通过tryLock()在失败的时候不会导致死锁。

3.示例

import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock; class Counter{
private Lock lock = new ReentrantLock();
private int value = 0;
public void add(int m){
lock.lock();
try{
value += m;
}finally {
lock.unlock();
}
}
public void dec(int m){
lock.lock();
try{
value -= m;
}finally {
lock.unlock();
}
}
public int get(){
lock.lock();
try{
return this.value;
}finally {
lock.unlock();
}
}
}
public class Main{
final static int LOOP = 100;
public static void main(String[] args) throws Exception{
Counter counter = new Counter();
Thread t1 = new Thread(){
public void run(){
for(int i=0;i<LOOP;i++){
counter.add(1);
}
}
};
Thread t2 = new Thread(){
public void run(){
for(int i=0;i<LOOP;i++){
counter.dec(1);
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.get());
}
}

4.总结:

  • ReentrantLock可以替代synchronized
  • ReentrantLock获取锁更安全
  • lock()获取锁在try...finally之前
  • 必须使用try... finally保证释放锁

廖雪峰Java11多线程编程-3高级concurrent包-1ReentrantLock的更多相关文章

  1. 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

    Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...

  2. 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合

    Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...

  3. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService

    Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...

  4. 廖雪峰Java11多线程编程-3高级concurrent包-9Fork_Join

    线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/J ...

  5. 廖雪峰Java11多线程编程-3高级concurrent包-8CompletableFuture

    使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get() ...

  6. 廖雪峰Java11多线程编程-3高级concurrent包-7Future

    JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPo ...

  7. 廖雪峰Java11多线程编程-3高级concurrent包-3Condition

    Condition实现等待和唤醒线程 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized可以使用wait和notify实现在条件不 ...

  8. 廖雪峰Java11多线程编程-3高级concurrent包-2ReadWriteLock

    ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共 ...

  9. 廖雪峰Java11多线程编程-2线程同步-3死锁

    1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...

随机推荐

  1. LeetCode 1108. Defanging an IP Address (IP 地址无效化)

    题目标签:String 题目给了我们一组 ip address,让我们把 . 变成 [.],这题可以用replace,但是这样做的话,好像没意义了.所以还是走一下array,具体看code. Java ...

  2. 用python写的自动转发邮件信息模板

    # -*- coding:utf-8 -*- #加密东西 def decrypt(key, s): c = bytearray(str(s).encode("gbk")) n = ...

  3. jquery click事件失效

    除了最基本的语法错误,还可能是因为,元素根本点击不到. z-index:99;

  4. Android Telephony分析(四) ---- TelephonyManager详解

    前言 TelephonyManager主要提供Telephony相关信息的查询/修改功能,以及Phone状态监听功能,封装的方法主要是提供给APP上层使用.TelephonyManager.java ...

  5. decimate、end、interp、resample工具箱函数

  6. 如何在Ubuntu 16.04上安装Nginx

    原文链接https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04 介绍 Nginx是世 ...

  7. JVM基本知识总结

    大概两三个月之前阅读了<深入理解Java虚拟机>(周志明著),也为了加深印象,这里简单的做下总结,想完整点了解JVM知识的也可以阅读本书,书写的不错,相当通俗易懂. 第一部分 内存管理机制 ...

  8. TwainCapabilities

    Twain Capabilities 2013年10月15日 ⁄ 综合 ⁄ 共 6098字 ⁄ 字号 小 中 大 ⁄ 评论关闭 转自:http://blog.163.com/lvan100@yeah/ ...

  9. 解决VS2012新建MVC4等项目时,收到此模板加载程序集“NuGet.VisualStudio.Interop…”的错误

    1.错误如图所示: 2.不管是VS2012,还是2013如果开始没安装Nuget包都或报这个错,因为VS2012就已经全面切换到使用NuGet这个第三方开源工具来管理项目包和引用模块了,使用VS201 ...

  10. 安装keepalived 出现configure: error: Popt libraries is required

    keepalived执行./configure --prefix=/usr/local/keepalived时报错:configure: error: Popt libraries is requir ...