原创

JUC包下Lock接口详解

源码:

public interface Lock {

    void lock();

    void lockInterruptibly() throws InterruptedException;

    boolean tryLock();

    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    void unlock();

    Condition newCondition();

}

lock():获取锁

  • 普通的获取锁功能,如果锁被别的线程获取则进行等待。
  • 不能像synchronized一样异常时自动释放锁,必须手动释放。一般在finally中释放锁。
  • 该方法不能被中断,如果进入死锁情况就会一直等待。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author weilai
 * @email 352342845@qq.com
 * @date 2020/3/23 12:58 下午
 */
public class DemoLock implements Runnable {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoLock());
        Thread t2 = new Thread(new DemoLock());
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "获取到锁");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + "释放锁");
        }
    }
}

output:

Thread-0获取到锁
Thread-0释放锁
Thread-1获取到锁
Thread-1释放锁

lockInterruptibly():可中断获取锁

该方法与lock()的区别是该方法索取锁可中断,会抛出InterruptedException异常。

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

/**
 * @author weilai
 * @email 352342845@qq.com
 * @date 2020/3/23 12:58 下午
 */
public class DemoLock implements Runnable {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoLock());
        Thread t2 = new Thread(new DemoLock());
        t1.start();
        t2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
        t2.interrupt();
    }

    @Override
    public void run() {
        try {
            lock.lockInterruptibly();
            try {
                System.out.println(Thread.currentThread().getName() + "获取到锁");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() + "休眠时被中断");
                }
            } finally {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + "释放锁");
            }
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + "等到获取锁被中断");
        }
    }
}

output:

Thread-0获取到锁
Thread-0休眠时被中断
Thread-0释放锁
Thread-1等到获取锁被中断

tryLock():尝试获取锁

该方法会尝试获取锁,不会阻塞,立刻会返回true、false。

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

/**
 * @author weilai
 * @email 352342845@qq.com
 * @date 2020/3/23 12:58 下午
 */
public class DemoLock implements Runnable {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoLock());
        Thread t2 = new Thread(new DemoLock());
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        if (lock.tryLock()) {
            try {
                System.out.println(Thread.currentThread().getName() + "获取到锁");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } finally {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + "解锁");
            }
        } else {
            System.out.println(Thread.currentThread().getName() + "未到锁");
        }
    }
}

tryLock(long time, TimeUnit unit):等待time时间后尝试获取锁

该方法阻塞到time时间后获取锁,返回true、false。该方法可中断,会抛出InterruptedException异常。

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

/**
 * @author weilai
 * @email 352342845@qq.com
 * @date 2020/3/23 12:58 下午
 */
public class DemoLock implements Runnable {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoLock());
        Thread t2 = new Thread(new DemoLock());
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        for (int i = 1; i < 100; i++) {
            try {
                if (lock.tryLock(100, TimeUnit.MILLISECONDS)) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "获取到锁");
                        Thread.sleep(1000);
                        break;
                    }finally {
                        lock.unlock();
                        System.out.println(Thread.currentThread().getName() + "解锁");
                    }
                } else {
                    System.out.println(Thread.currentThread().getName() + "未获取到锁,第" + i + "次尝试");
                }
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "索取锁被打断");
            }
        }
    }
}

output:

Thread-0获取到锁
Thread-1未获取到锁,第1次尝试
Thread-1未获取到锁,第2次尝试
Thread-1未获取到锁,第3次尝试
Thread-1未获取到锁,第4次尝试
Thread-1未获取到锁,第5次尝试
Thread-1未获取到锁,第6次尝试
Thread-1未获取到锁,第7次尝试
Thread-1未获取到锁,第8次尝试
Thread-1未获取到锁,第9次尝试
Thread-0解锁
Thread-1获取到锁
Thread-1解锁

unlock():解锁

解锁操作,释放拿到的锁。

线程可见性

Lock接口与synchronized一样保证了线程可见性,即线程A中所的所有获取到锁之后的操作对线程B就是线程可见的。

正文到此结束
本文目录