Java多线程学习之重入锁 您所在的位置:网站首页 java多线程乐观锁实现代码 Java多线程学习之重入锁

Java多线程学习之重入锁

#Java多线程学习之重入锁| 来源: 网络整理| 查看: 265

可重入锁的概念

可重入:某个线程(Thread-A)已经获取到某个锁(lock-A),在该线程(Thread-A)未解锁前又再次获取到此锁(lock-A)而不出现死锁。

可重入锁:能被某个线程在未解锁前重复获取而不出现死锁现象的锁。

可重入锁的例子 synchronized

示例代码:

public class ReentryLock1 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { int i = 1; synchronized (this) { System.out.println("第" + i + "次获取锁,这个锁是:" + this); for (i = 2; i < 10; i++) { synchronized (this) { System.out.println("第" + i + "次获取锁,这个锁是:" + this); } } } } }).start(); } }

结果:可正常运行,无死锁现象,且锁对象是同一个

ReentrantLock

示例代码:

public class ReentryLock2 { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); new Thread(new Runnable() { @Override public void run() { try { int i = 1; lock.lock(); System.out.println("第" + i + "次获取锁,这个锁是:" + lock); for (i = 2; i < 10; i++) { try { lock.lock(); System.out.println("第" + i + "次获取锁,这个锁是:" + lock); } finally { lock.unlock(); } } } finally { lock.unlock(); } } }).start(); } }

结果:可正常运行,无死锁现象,且锁对象是同一个

 Synchronized和ReentrantLock 对比

1、性质不同:Synchronized是关键字,它的‘锁’是Java内置的功能;而ReentrantLock是一个实现Lock接口的类,需要调用方法lock()和unlock(),配合try/finally语句块来实现‘锁’功能;

2、作用域不同:

Synchronized

修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象;修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;修饰一个静态的方法:其作用的范围是整个方法,作用的对象是这个类的所有对象;修饰一个代码块:被修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码块,作用的对象是调用这个代码块的对象。

ReentrantLock

修饰代码块:以方法lock()开始,以unlock()结束。

3、结束方式不同:Synchronized一般是修饰的方法和代码块执行完以后才解锁,而ReentrantLock的结束取决于什么时候调用unlock()方法。

4、性能不同:JDK6以前Synchronized还是重量级锁,性能很差,虽然从JDK6开始对Synchronized进行性能上的优化,但是高并发的情况下还是比ReentrantLock要差。(当然一般情况下Synchronized就足够满足大部分项目了,且使用方便,不用考虑手动解锁的问题)

补充:

ReentrantLock使用时尽量配合try/finally语句块来保证每次‘锁’都被手动‘解锁’,即lock()和unlock()调用方法次数要保持一致,不然可能会死锁。例如:

数量一致时:同一个锁对象在被多次调用时可以正常运行。 public class ReentryLock3 { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { lock.lock(); System.out.println("threadName:" + Thread.currentThread().getName()); } finally { lock.unlock(); } } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { lock.lock(); System.out.println("threadName:" + Thread.currentThread().getName()); } finally { lock.unlock(); } } } }).start(); } }

数量不一致时:同一个锁对象在被多次调用时无法保证正常运行。 public class ReentryLock3 { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); new Thread(new Runnable() { @Override public void run() { //此处改为多次lock只在外面unlock一次用作测试 try { for (int i = 0; i < 5; i++) { lock.lock(); System.out.println("threadName:" + Thread.currentThread().getName()); } } finally { lock.unlock(); } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { lock.lock(); System.out.println("threadName:" + Thread.currentThread().getName()); } finally { lock.unlock(); } } } }).start(); } }

结果:因为第一个线程未完全解锁,所以第二个线程无法正常获取到锁,导致死锁程序无法运行下去。

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有