通过查看 Lock 的源码可知,Lock是一个接口。Lock有一个实现类 ReentrantLock

1public interface Lock {
 2    void lock();//获得锁,如果锁已经被占用,则等待
 3
 4    void lockInterruptibly() throws InterruptedException;//获得锁,但优先响应中断
 5
 6    boolean tryLock();// 尝试获得锁,如果成功,返回true,失败返回false。该方法不等待,立即返回
 7
 8    boolean tryLock(long time, TimeUnit unit) throws InterruptedException; //   在给定时间内尝试获得锁
 9
10    void unlock();   //用来释放锁
11
12    Condition newCondition();
13}

Lock方法

场景:如果发现该操作已经在执行,等待一个一个执行(同步执行,类似synchronized)
1public class Lockone implements Runnable{
 2    public static ReentrantLock lock=new ReentrantLock();
 3    @Override
 4    public void run() {
 5        try{
 6                lock.lock();
 7            } finally {
 8                lock.unlock();
 9            }           
10
11    }
12    public static void main(String[] args) {
13        Lockone Lock=new Lockone();
14        Thread t1=new Thread(Lock);
15        Thread t2=new Thread(Lock);
16        t1.start();
17        t2.start();
18    }
19}

lockInterruptibly

场景:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作
  • 什么是中断响应?
    对于synchronized来说,如果一个线程在等待锁,那么结果只有两种,要么它获得这把锁继续执行,要么它就保持等待。而重入锁,则提供另一种可能,那就是线程可以被中断。也就是在等待锁的过程中,程序可以根据需要取消对锁的请求。中断正式提供了一套类似机制,如果一个线程正在等待锁,那么他依然可以接到一个通知,被告知,无需在等待,可以停止工作了。

举个例子:

1public class LockInter implements Runnable{
 2    public static ReentrantLock lock=new ReentrantLock(true);
 3    @Override
 4    public void run() {
 5        try {
 6            //lock.lockInterruptibly();
 7            lock.lock();
 8            System.out.println(Thread.currentThread().getName()+"running");
 9            Thread.sleep(5000);
10            lock.unlock();
11            System.out.println(Thread.currentThread().getName()+" finished");
12        } catch (InterruptedException e) {
13            System.out.println(Thread.currentThread().getName()+" interrupted");
14        }
15
16    }
17    public static void main(String[] args) {
18        LockInter mm=new LockInter();
19        Thread t1=new Thread(mm);
20        Thread t2=new Thread(mm);
21        t1.start();
22        t2.start();
23        t2.interrupt();
24    }
25
26
27}

6运行的结果是

1Thread-0running
2Thread-1 interrupted
3Thread-0 finished

7运行的结果是

1Thread-0running
2Thread-0 finished
3Thread-1running
4Thread-1 interrupted

看出差别来了嘛。lock方法比较死板,必须得等当前线程结束,才会响应其他线程的中断

tryLock

场景:如果发现该操作已经在执行中则不再执行(有状态执行)

有返回值,它表示用来尝试获取锁,如果获取成功返回true;如果获取失败(即锁已被其他线程获取),则返回失败

1import java.util.concurrent.TimeUnit;
 2import java.util.concurrent.locks.ReentrantLock;
 3
 4public class TimeLock implements Runnable{
 5    public static ReentrantLock lock=new ReentrantLock();
 6
 7    @Override
 8    public void run() {
 9        try {
10            if(lock.tryLock(5, TimeUnit.SECONDS)){
11                Thread.sleep(6000);
12            }else{
13                System.out.println("获取失败");
14            }       
15        } catch (InterruptedException e) {
16            e.printStackTrace();
17        }finally {
18            if (lock.isHeldByCurrentThread()) {
19                lock.unlock();
20            }       
21        }
22    }
23    public static void main(String[] args) {
24        TimeLock timeLock=new TimeLock();
25        Thread t1=new Thread(timeLock);
26        Thread t2=new Thread(timeLock);
27        t1.start();
28        t2.start();
29    }
30}

isHeldByCurrentThread() 查询当前线程是否保持锁定
trylock()两个参数第一个是等待时长,第二个表示计时单位
运行结果:

1获取失败

公平锁和非公平锁

  • 公平锁是指多个线程等待同一个锁时,必须按照申请锁的先后顺序来一次获得锁
    特点:等待锁的线程不会饿死,但整体效率相对低一些
  • 非公平锁是指可以不按照顺序,可以抢占锁
    特点:整体效率高,但有些线程会饿死或者说很早就在等待锁,但要等很久才会获得锁
    重入锁有这样一个构造函数,对公平性进行设置。当fair为true时,表示此锁是公平的
1public ReentrantLock(boolean fair) {
2        sync = fair ? new FairSync() : new NonfairSync();
3    }

举个公平锁的例子:

1import java.util.concurrent.locks.ReentrantLock;
 2
 3public class FairLock implements Runnable{
 4    public static ReentrantLock lock=new ReentrantLock(true);
 5    @Override
 6    public void run() {
 7        while (true) {
 8            try {
 9                lock.lock();
10                System.out.println(Thread.currentThread().getName()+"获得锁");
11            } finally {
12                lock.unlock();
13            }           
14        }
15    }
16    public static void main(String[] args) {
17        FairLock fairLock=new FairLock();
18        Thread t1=new Thread(fairLock);
19        Thread t2=new Thread(fairLock);
20        t1.start();
21        t2.start();
22    }
23}

运行结果

1Thread-0获得锁
2Thread-1获得锁
3Thread-0获得锁
4Thread-1获得锁    //只截取一部分,但可以看出线程是按照顺序执行

newCondition

下回分解