Reentranlock--->
Reentrantlock—可重入锁,之前我们学过synchronized,这个锁也是可重入的,那么为什么还需要一个专门的可重入锁?这是因为虽然两者都是可重入的,但ReentrantLock相比synchronized功能更加丰富,使用更为灵活,也更适合复杂的并发场景,因此可以用于替代synchronized。
Reentranlock的方法
- lock():获取锁,不拿到锁誓不罢休
- tryLock():尝试获取锁,能拿到就拿,拿不到就溜
- lockInterruptibly():获取锁,线程在请求被阻塞时,可以被interrupt
- unlock():释放锁,需要手动释放,一般放在finally语句块中
Reentranlock的基础用法
public class ReLockTest1 {
Lock lock = new ReentrantLock();
void m1() {
try {
lock.lock();
for (int i = 0; i < 5; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
void m2() {
try {
lock.lock();
System.out.println("m2...");
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReLockTest1 reLock = new ReLockTest1();
new Thread(reLock::m1, "t1").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(reLock::m2, "t2").start();
}
}
这个程序中,首先,需要new一个Reentranlock对象lock,使用lock去锁住对象,与synchronized作用一样,但是,需要注意这些语句要写在try语句块中,然后在finally中手动释放锁。主程序中,两个线程,分别获取锁,然后执行方法。最后得到的结果: 0 1 2 3 4 m2…
tryLock
其中,Reentranlock更优秀的一点就是可以在一定时间的范围内尝试获取锁,如果过了这个时间没有得到,那也不强求,如下代码:
public class TryLockTest {
Lock lock = new ReentrantLock();
boolean isLocked = false;
void m1() {
try {
isLocked = lock.tryLock(3, TimeUnit.SECONDS); //time可变
System.out.println("m1..." + isLocked);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(isLocked)
lock.unlock();
}
}
void m2() {
try {
lock.lock();
for(int i = 0; i < 5; i++) {
TimeUnit.SECONDS.sleep(1);
System.out.println(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
TryLockTest tryLock = new TryLockTest();
new Thread(tryLock::m2).start();
new Thread(tryLock::m1).start();
}
}
m1方法在3秒内进行tryLock,随后输出语句并判断锁的状态,m2方法lock,并在5秒内的每秒输出数字,main函数中创建两个线程分别调用方法,随后执行。执行结果:如果tryLock秒数小于5,则isLocked状态为false,否则为true。
值得注意的是:tryLock并不是在一开始就开始抢锁的,而是在设置秒数是最大时间出进行时间片的抢夺。
公平不公平?
Reentranlock默认是非公平锁,如果想要成为公平锁,那么在需要new Reentranlock(true),这样传参成为公平锁,如果传参为false或者没有参数则为非公平锁。来段代码,可以看出公不公平的结果体现
public class IsFair implements Runnable {
Lock lock = new ReentrantLock(/*true*/);
public void run() {
for (int i = 0; i < 5; i++) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "获得锁");
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
IsFair isFair = new IsFair();
Thread t1 = new Thread(isFair);
Thread t2 = new Thread(isFair);
t1.start();
t2.start();
}
}
测试结果: