目录
ReentrantLock使用示例lock.lockInterruptibly();
有了synchronized为什么还要Lock
Synchronized | ReentrantLock | |
类型 | 关键字:修饰方法或者代码块 | 接口:常用的五个方法 |
隐式获取锁,把锁的获取和释放固化了,即先获取再释放 |
1、能够尝试非阻塞获取锁(tryLock()) 2、能够响应中断,被中断时,会跑出中断异常,同时会释放锁 3、能够超时获取锁tryLock(long time, TimeUnit unit) |
|
可重入(原理:线程持有者和计数器) | 支持 | 已经获取到锁的线程,能够再次调用lock()方法获取锁而不被阻塞 |
公平:先对锁获取的先被满足,效率低 非公平:多个线程不管先后竞争锁 |
非公平 | 通过构造函数自定义public ReentrantLock(boolean fair) |
lock常用的方法
方法名称 | 描述 |
void lock(); | 获取锁,调用该方法当前线程会获取锁,当获取锁后,从该方法返回 |
void lockInterruptibly() throws InterruptedException; | 可中断地获取锁,和lock()方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程 |
boolean tryLock(); | 尝试获取锁,调用后回立即返回,获取到锁true,否则返回fasle |
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; |
1、在超时时间获取锁:true 2、在超时时间内被中断:false 3、超时:false |
void unlock(); | 释放锁 |
lock使用的标准代码
lock.lock();
try{
count++;
}finally{
lock.unLock();
}
ReentrantLock使用示例lock和unlock:
两个线程对count自增1000,另一个线程对count自减1000
public class MyReentrantLock {
int count = 1000;
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
myReentrantLock.count++;
} finally {
lock.unlock();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
myReentrantLock.count--;
} finally {
lock.unlock();
}
}
}).start();
//主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
Thread.sleep(1000);
System.out.println(myReentrantLock.count);
}
}
结果:1000
ReentrantLock使用示例tryLock()
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {
Thread.sleep(100);
myReentrantLock.count++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
thread.start();
//thread.interrupt();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
if (lock.tryLock()) {
try {
myReentrantLock.count--;
} finally {
lock.unlock();
}
}
}
});
//thread2.interrupt();
//主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
Thread.sleep(1000);
System.out.println(myReentrantLock.count);
}
}
结果在:1000-1010之间
ReentrantLock使用示例lock.lockInterruptibly();
public class MyReentrantLock {
int count = 1000;
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
lock.lockInterruptibly();
Thread.sleep(100);
myReentrantLock.count--;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
thread2.start();
Thread.sleep(100);
thread2.interrupt();
//主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
Thread.sleep(1200);
System.out.println(myReentrantLock.count);
}
}
结果:
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:39)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:45)
at java.lang.Thread.run(Thread.java:748)
999