ReenTrantLock和Synchronized
1.jdk中常用的独占锁有两种:Synchronized,ReenTrantLock。两种锁在性能上差别不大,但ReenTrantLock手动加锁,解锁,更加灵活,功能更加丰富
1)独占锁,可重入锁
public class TestReenTrantLock {static Lock lock = new ReentrantLock(true);
public static void main(String[] args) {
//可重入锁:一个线程多次获取同一个对象上的锁。可重入锁的意义之一在于防止死锁
实现原理:当线程获取锁时,jvm将记录锁的占有者,并将锁中的计数器加1,同一个线程再次获得锁,计数器再次加1。未被占用的锁,计数器为0。当线程退出同步块,计数器值将递减,直到计数器值为0,锁被释放。其他线程才能获得锁
独占锁:一个锁一次只能被一个线程占有
method();
method1();
lock.unlock();
lock.unlock();
}public static void method(){
lock.lock();
System.out.println("第一次获取锁");
}public static void method1(){
lock.lock();
System.out.println("第二次获取锁");
}
}
这里在method中获取了TestReenTrantLock类锁,调用method1时再一次获取了TestReenTrantLock类锁,这就是可重入锁
【ReenTrantLock和Synchronized】2)可以实现公平锁
public class FairReenTrantLock {/**
* 公平锁:当锁可用时,在锁上等待时间最长的线程获取锁的使用权
* 无参数或为fasle,为非公平锁
* 非公平锁:随机获得锁的使用权
*/
static Lock lock = new ReentrantLock(true);
public static void main(String[] args) {
for (int i=0;
i<5;
i++){
new Thread(new ThreadDemo()).start();
}
}static class ThreadDemo implements Runnable{public ThreadDemo(){}@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
}catch (Exception e){
e.printStackTrace();
}
for(int i=0;
i<2;
i++){
lock.lock();
System.out.println("获得锁的线程"+Thread.currentThread().getName());
lock.unlock();
}
}
}}
文章图片
文章图片
3)可以响应线程中断
- 首先了解一下 public void interrupt();
(属于ThreadL类)
文章图片
public class TestInterrupt {public static void main(String[] args) throws InterruptedException {
Thread testThread = new TestThread();
testThread.start();
testThread.interrupt();
}/*
*下面测试的三个方法都会阻塞线程,如果没有使用这个三个方法,线程会直接走完,
*而且isInterrupted()为true
*使用了其中一个,会抛出InterruptedException,isInterrupted()为false
*/
static class TestThread extends Thread {@Override
public void run() {
System.out.println("线程开始运行");
try {
//TimeUnit.SECONDS.sleep(5);
//wait();
join();
}catch (Exception e){
System.out.println("线程发生异常"+e);
System.out.println(Thread.currentThread().isInterrupted());
}
System.out.println("线程结束运行");
}
}
}
- 响应中断案例
public class LockInterruptibly {static Lock firstLock = new ReentrantLock();
static Lock secondLock = new ReentrantLock();
public static void main(String[] args) {
Thread firstthread = new Thread(new ThreadDemo(firstLock,secondLock));
Thread secondThread = new Thread(new ThreadDemo(secondLock,firstLock));
firstthread.start();
secondThread.start();
firstthread.interrupt();
}static class ThreadDemo implements Runnable {
private Lock firstLock;
private Lock secondLock;
public ThreadDemo(Lock firstLock,Lock secondLock){
this.firstLock = firstLock;
this.secondLock = secondLock;
}//会中断处于等待的线程,释放锁,然后另一个线程获取锁,继续走
@Override
public void run() {
try {
firstLock.lockInterruptibly();
TimeUnit.SECONDS.sleep(1);
secondLock.lockInterruptibly();
}catch (Exception e){
e.printStackTrace();
}finally {
firstLock.unlock();
secondLock.unlock();
System.out.println(Thread.currentThread().getName()+"正常结束");
}
}
}
}
- 不响应中断案例
public class TestSynchronized {static Object resource1 = new Object();
static Object resource2 = new Object();
public static void main(String[] args) {
Thread thread1 = new TestSynchronizedThread(resource1,resource2);
Thread thread2 = new TestSynchronizedThread(resource2,resource1);
thread1.start();
thread2.start();
thread1.interrupt();
//中断线程,
}static class TestSynchronizedThread extends Thread {
Object resource1;
Object resource2;
public TestSynchronizedThread(Object resource1,Object resource2){
this.resource1 = resource1;
this.resource2 = resource2;
}//即使跑出异常,也不会中断线程,两个线程继续互相等待资源,造成死锁
@Override
public void run() {
synchronized (resource1){
System.out.println(Thread.currentThread().getName()+"--111");
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName()+"--222");
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"--333");
}System.out.println(Thread.currentThread().getName()+"--444");
synchronized (resource2){
System.out.println(555);
}
}}
}
}
4)获取锁时,限时等待
5)利用condition实现等待通知机制,
6)condition实现阻塞队列
synchronized
推荐阅读
- 急于表达——往往欲速则不达
- 第三节|第三节 快乐和幸福(12)
- 20170612时间和注意力开销记录
- 2.6|2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
- 对称加密和非对称加密的区别
- 眼光要放高远
- 樱花雨
- 前任
- 2020-04-07vue中Axios的封装和API接口的管理
- 烦恼和幸福