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. 开发中运行mysql脚本,发现提示mysql提示Column count doesn't match value count at row 1错误

    开发中运行mysql脚本,发现提示mysql提示Column count doesn't match value count at row 1错误, 调试后发现是由于写的SQL语句里列的数目和后面的值 ...

  2. Openstack Nova 源码分析 — Create instances (nova-conductor阶段)

    目录 目录 前言 Instance Flavor Instance Status Virt Driver Resource Tracker nova-conductor Create Instance ...

  3. 2019 IEEEXtreme 13.0 题解记录

    比赛时间 2019.10.19 8:00 - 2019.10.20 8:00 比赛网站 https://csacademy.com/ieeextreme13 // 连续24小时做题真的是极限体验 // ...

  4. Python3 From Zero——{最初的意识:007~函数}

    一.编写可接受任意数量参数的函数:*.** >>> def test(x, *args, y, **kwargs): ... pass ... >>> test(1 ...

  5. Java设计模式(一)外观模式(门面模式)- 结构型模式

    模式的定义 门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如下:要求一个子系统的外部与其内部通信必须通过一个统一的对象进行.门面模式提供一个高层次的接口,使得 ...

  6. jwt、oauth2和oidc等认证授权技术的理解

    前言 jwt.oauth2.oidc等,都是和认证授权相关的规范或者解决方案,因此要理解他们,就需要从业务场景的适用性一步步的分析和认识. 一.认证授权业务场景理解 就个人目前的理解来看,一个好的软件 ...

  7. jupyter安装_pip法

    安装jupyter notebook的流程(注意python至少需要3.6版本) python -m pip install jupyter  #安装jupyter python -m pip ins ...

  8. 312. 戳气球【困难】【区间DP】

    题目链接 有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中. 现在要求你戳破所有的气球.每当你戳破一个气球 i 时,你可以获得 nums[left] * ...

  9. C# async await 举个栗子

    首先,async 和 await 代表异步执行和等待. async是一个标记,告诉编译器,我可能是一个异步方法. await 代表等待,告诉编译器,这里等我返回结果. 下面,我们简单说一下. 一 , ...

  10. excel破解工作簿与工作表保护

    1.工作簿保护 1.1.使用压缩文件打开文件