这篇文章主要介绍了Java并发编程之重入锁与读写锁,文中相关实例代码详细,测试可用,具有一定参考价值,需要的朋友可以了解下。

重入锁

重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞,该特性的实现需要解决以下两个问题。

1、线程再次获取锁。锁需要去识别获取锁的线程是否为当前占据锁的线程,如果是,则再次成功获取。

2、锁的最终释放。线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁。锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放。

Java里面内置锁(synchronize)和Lock(ReentrantLock)都是可重入的

synchronized 实例

package com.home;

public class SynchronizedTest implements Runnable {

public synchronized void method1() {

System.out.println("method1获得锁,正常运行!");

method2();

}

public synchronized void method2() {

System.out.println("method2获得锁,也正常运行!");

}

@Override

public void run() {

method1();

}

public static void main(String[] args) {

SynchronizedTest st = new SynchronizedTest();

new Thread(st).start();

new Thread(st).start();

}

}

Lock 实例

package com.home;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class LockTest implements Runnable {

Lock lock = new ReentrantLock();

public void method1() {

lock.lock();

System.out.println("method1获得锁,正常运行!");

method2();

lock.unlock();

}

public void method2() {

lock.lock();

System.out.println("method2获得锁,也正常运行!");

lock.unlock();

}

@Override

public void run() {

method1();

}

public static void main(String[] args) {

LockTest lt = new LockTest();

new Thread(lt).start();

new Thread(lt).start();

}

}

两个例子最后的结果都是正确的,结果如下:

method1获得锁,正常运行!

method2获得锁,也正常运行!

method1获得锁,正常运行!

method2获得锁,也正常运行!

可重入锁最大的作用是避免死锁

读写锁

读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。

可重入读写锁 ReentrantReadWriteLock

ReentrantReadWriteLock对象提供了readLock()和writeLock()方法, 用于获取读取锁和写入锁.

读取锁允许多个reader线程同时持有, 而写入锁最多只能有一个writter线程持有.

读写锁的使用场合: 读取共享数据的频率远大于修改共享数据的频率. 在上述场合下, 使用读写锁控制共享资源的访问, 可以提高并发性能.

如果一个线程已经持有了写入锁, 则可以再持有读写锁. 相反, 如果一个线程已经持有了读取锁, 则在释放该读取锁之前, 不能再持有写入锁.

可以调用写入锁的newCondition()方法获取与该写入锁绑定的Condition对象, 此时与普通的互斥锁并没有什么区别. 但是调用读取锁的newCondition()方法将抛出异常.

例子

package com.home;

import java.util.Random;

import java.util.concurrent.locks.ReadWriteLock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

class ReadWrte {

// 共享数据,可以多个线程读数据,只能有一个线程写数据

private int data;

// 创建读写锁

ReadWriteLock rwLock = new ReentrantReadWriteLock();

/**

* 读数据,上读锁

*/

public void get() {

// 读锁

rwLock.readLock().lock();

try {

System.out.println(Thread.currentThread().getName() + ",Read!");

Thread.sleep((long) Math.random() * 1000);

System.out.println(Thread.currentThread().getName() + " 读出的数据为:" +

this.getData());

} catch (Exception e) {

e.printStackTrace();

} finally {

rwLock.readLock().unlock();

}

}

/**

* 写数据,上写锁

*

* @param data

*/

public void put(int data) {

// 写锁

rwLock.writeLock().lock();

try {

System.out.println(Thread.currentThread().getName() + ",Write!");

Thread.sleep((long) Math.random() * 1000);

this.setData(data);

System.out.println(Thread.currentThread().getName() + " 写入的数据为:" +

this.getData());

} catch (InterruptedException e) {

e.printStackTrace();

} finally {

rwLock.writeLock().unlock();

}

}

public int getData() {

return data;

}

public void setData(int data) {

this.data = data;

}

}

/**

* 测试类

*

* @author itmyhome

*

*/

public class ReadWriteLockTest {

/**

* @param args

*/

public static void main(String[] args) {

// 创建ReadWrte对象

final ReadWrte rw = new ReadWrte();

for (int i = 0; i < 10; i++) {

// 创建并启动10个读线程

new Thread(new Runnable() {

@Override

public void run() {

rw.get();

}

}).start();

// 创建并启动10个写线程

new Thread(new Runnable() {

@Override

public void run() {

// 写入一个随机数

rw.put(new Random().nextInt(8));

}

}).start();

}

}

}

输出为

Thread-0,Read!

Thread-4,Read!

Thread-8,Read!

Thread-12,Read!

Thread-0 读出的数据为:0

Thread-4 读出的数据为:0

Thread-8 读出的数据为:0

Thread-12 读出的数据为:0

Thread-19,Write!

Thread-19 写入的数据为:5

Thread-7,Write!

Thread-7 写入的数据为:7

Thread-3,Write!

Thread-3 写入的数据为:4

Thread-16,Read!

Thread-16 读出的数据为:4

Thread-11,Write!

Thread-11 写入的数据为:0

Thread-15,Write!

Thread-15 写入的数据为:5

Thread-2,Read!

Thread-2 读出的数据为:5

Thread-17,Write!

Thread-17 写入的数据为:2

Thread-6,Read!

Thread-6 读出的数据为:2

Thread-1,Write!

Thread-1 写入的数据为:5

Thread-13,Write!

Thread-13 写入的数据为:4

Thread-9,Write!

Thread-9 写入的数据为:7

Thread-5,Write!

Thread-5 写入的数据为:2

Thread-10,Read!

Thread-10 读出的数据为:2

Thread-18,Read!

Thread-14,Read!

Thread-18 读出的数据为:2

Thread-14 读出的数据为:2

从图中我们可以看出,可以多个线程同时读,但只能一个线程写,即写数据和写入数据一并完成。

总结

java读写锁死锁例子_Java并发关于重入锁与读写锁的详解相关推荐

  1. java 并发锁_Java并发教程–重入锁

    java 并发锁 Java的synced关键字是一个很棒的工具–它使我们可以通过一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访 ...

  2. 谈谈java并发锁(重入锁、读写锁、公平锁)

    目录 重入锁 简单重入锁 重入锁的等待通知(Condition) 多Condition 公平锁和非公平锁 读写锁ReentrantReadWriteLock 锁优化总结: 重入锁和读写锁,他们具有比s ...

  3. 锁Lock,主要是重入锁和读写锁

    2019独角兽企业重金招聘Python工程师标准>>> 在java多线程中,我们可以使用synchronized关键字来实现线程之间的同步互斥工作.还有一个更优秀的机制去完成这个&q ...

  4. Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除

    文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...

  5. java dom4j读写锁,java锁的深度化-重入锁,读写锁,乐观锁,悲观锁

    1.重入锁 目的:避免死锁的现象 锁作为并发共享数据,保证一致性的工具,在java平台有多种实现synchronized(重量级)和ReentrantLock(轻量级)等等,这些已经写好提供的锁为我们 ...

  6. Java并发教程–重入锁

    Java的synced关键字是一个很棒的工具–它使我们能够以一种简单可靠的方式来同步对关键部分的访问,而且也不难理解. 但是有时我们需要对同步进行更多控制. 我们要么需要分别控制访问类型(读取和写入) ...

  7. java 线程的可重入锁_java 多线程-可重入锁

    可重入锁:锁可以连续使用 计数器+判断进入的线程是不是已经锁定的线程,如果是那就不用等待,直接使用 public class my { public static void main(String[] ...

  8. java调用其他程序吗_java本地方法如何调用其他程序函数,方法详解

    JNI是Java Native Interface的缩写,中文为JAVA本地调用.从Java 1.1 开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许J ...

  9. java final修饰的类_java final修饰符使用总结,final修饰类详解

    下面要继续给大家讲到的就是java final修饰符方面的知识,主要是java final修饰符使用总的一些总结,以及一些final修饰类方面的一些知识. java final修饰符使用总结 首先我们 ...

最新文章

  1. 重定向后,如何通过浏览器返回定向之前的页面?
  2. 面试官问:什么是布隆过滤器?
  3. MacBook(macOS) 如何安装 Homebrew Cask(作废)
  4. linux编译c 自动化,Linux江湖06:感悟GNU C以及将Vim打造成C/C++的半自动化IDE
  5. wxpython和tkinter哪个好_为什么很多Python开发者写GUI不用Tkinter,而要选择PyQt和wxPython或其他?...
  6. ict测试机台_ICT自动测试机 PTI-818S 深圳市派捷电子科技有限公司
  7. 计算机操作知识试题及答案真题,计算机操作系统期末考试题及答案
  8. 【something】简单的平均脸制作
  9. OSChina 周三乱弹 ——找女朋友都是双胞胎
  10. java后台实现CKFinder2.3版本+阿里OSS存储
  11. Arduino ESP8266 SPI-FFS存储区域
  12. rn+android+sdk,RN与Android原生交互
  13. 自定义协议推送的设计
  14. 把16 支球队随机分为4 个组。
  15. HSV与HSI颜色空间的区别以及和RGB之间的转换
  16. 宁波栎社机场停车场怎么收费,栎社机场停车场收费标准
  17. AES128加密算法与实现1
  18. 三菱PLC分拣程序基于三菱FX系列的分拣程序,可用于学习
  19. 施耐德马达保护器LTMR_08EBD+EV40与施耐德M580PLC通讯简单配置
  20. 看看国内哪家银行的缩写最牛

热门文章

  1. Epic融资20亿,离元宇宙更进一步
  2. 涉及上千款,2021 Chrome插件性能影响分析报告新鲜出炉
  3. iOS 之如何利用 RunLoop 原理去监控卡顿?
  4. 求求了!让 Python 的热搜消失吧!!
  5. 一个核心系统 3 万多行代码的重构之旅
  6. 关于自然语言处理,数据科学家需要了解的 7 项技术
  7. 被高估了的测试驱动开发?
  8. 十步教你成为数据科学家!
  9. 程序员离无人值班有多远?
  10. Vim 激荡 30 年发展史