synchronized 锁和 Lock 锁的区别
Lock 锁,Java类,synchronized,关键字。
synchronized 无法判断是否获得锁,获得失败进入阻塞,Lock 类通过 tryLock()方法,尝试获取,失败不会阻塞。
synchronized 同步完成自动释放锁,Lock 类在 finally {} 代码块手动释放。
一、Lock锁
创建一个Runnable,实现run方法。
public void run() {
String threadName = Thread.currentThread().getName();
lock.lock();
try {
Log.d(TAG, "线程:" + threadName + " 获得锁。");
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
Log.d(TAG, "线程:" + threadName + " 获得锁。");
}
}
开启两个线程,运行LockRunnable任务。
LockRunnable lockRunnable = new LockRunnable();
Thread one = new Thread(lockRunnable);
one.start();
Thread two = new Thread(lockRunnable);
two.start();
第一个线程先获得锁,另一个线程等待,直到unlock()方法释放锁,第二个线程才会获得锁,synchronized 无法判断线程是否获得锁,Lock类有一个tryLock()方法,改变代码。
public void run() {
String threadName = Thread.currentThread().getName();
if (lock.tryLock()) {
try {
Log.d(TAG, "线程:" + threadName + " 获得锁。");
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} else {
Log.d(TAG, "线程:" + threadName + " 获取锁失败。");
}
}
修改run方法,一个线程在Lock的tryLock方法,尝试获取锁,判断该线程是否获得锁,成功获取,返回标志继续执行,未成功获取锁也不会等待,返回false,继续走else方法,synchronized关键字当线程竞争失败时会阻塞等待。
synchronized同步代码执行完毕,自动释放锁,Lock类需要在finally代码块手动释放,Lock.unlock()方法。
二、lockInterruptibly方法
Lock的lock方法,第一个线程获得锁,第二个线程休眠。在当前条件下,执行休眠线程2的中断方法。
//线程1
LockRunnable lockRunnable = new LockRunnable();
Thread one = new Thread(lockRunnable);
one.start();
try {
//确保one先竞争到锁
Thread.sleep(500);
}catch (Exception e){
}
//线程2
Thread two = new Thread(lockRunnable);
two.start();
try {
//让竞争锁失败而休眠的2线程中断。线程2仍会休眠,
//线程1释放锁后,线程2竞争到锁,执行时sleep会检查到中断状态,异常
Thread.sleep(1000);
two.interrupt();
}catch (Exception e){
}
线程2处于竞争锁失败的休眠中,lock方法上锁,线程2对中断方法不感冒,一旦获取到锁,在sleep方法时,会根据中断标志抛出异常。
Lock的lockInterruptibly方法,在线程2休眠时,中断方法,会导致线程2在等待锁的lockInterruptibly方法处抛出InterruptedException异常,这时,线程2并未获得锁,finally代码段释放锁将发生IllegalMonitorStateException崩溃。
任重而道远
网友评论