# ReentrantLock

相对于synchronized它具备如下特点

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量
    与synchronized一样,都支持可重入

# 语法

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class Demo {

    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();
        try {
            log.info("do something");
        } finally {
            lock.unlock();
        }
    }
}

# 可重入

可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class Demo {

    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();
        try {
            log.info("do something");
            method();
        } finally {
            lock.unlock();
        }
    }

    static void method() {
        lock.lock();
        try {
            log.info("method");
            method2();
        } finally {
            lock.unlock();
        }
    }


    static void method2() {
        lock.lock();
        try {
            log.info("method2");
        } finally {
            lock.unlock();
        }
    }   
}

# 可打断


import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class Demo {

    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            try {
                //如果没有竞争那么此方法就会获取Lock对象锁
                //如果有竞争就进入阻塞队列,可以被其它线程用lockInterruptibly方法打断
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                log.info("未获取到锁");
                throw new RuntimeException(e);
            }
            log.info("获取到锁");
        }, "t1");


        lock.lock();
        thread.start();
        try {
            log.info("do something");
            log.info("打断thread");
            thread.interrupt();
        } finally {
            lock.unlock();
        }
    }

}

# 锁超时

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class Demo {

    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                if (!lock.tryLock(1, TimeUnit.SECONDS)) {
                    log.info("未获取到锁,不继续执行");
                    return;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            try {
                log.info("获取到锁");
            } finally {
                lock.unlock();
            }
        }, "t1").start();

        lock.lock();
        try {
            lock.lock();
            log.info("main do something");
        } finally {
            lock.unlock();
        }
    }

}

# 公平锁

ReentrantLock默认是不公平的

  static ReentrantLock lock = new ReentrantLock(true);

# 条件变量

# 语法

使用流程

  • await前需要获得锁
  • await执行后,会释放锁,进入conditionObject等待
  • await的线程被唤醒 (或打断、或超时)取重新竞争lock锁
  • 竞争lock锁成功后,从await后继续执行
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class Demo {

    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        //创建
        Condition condition = lock.newCondition();

        //需要先加锁
        lock.lock();
        try {
            //进入等待
            condition.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        condition.signal();
    }
}