重入锁

重入锁,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁阻塞,该特性的实现需要解决以下两个问题。
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
# 读写锁
# 编程实现读写锁
# 无锁并发编程
# java并发编程StampedLock高性能读写锁详解
# java并发编程中ReentrantLock可重入读写锁
# Java并发之搞懂读写锁
# Java并发编程之ReadWriteLock读写锁的操作方法
# Java并发编程之显示锁ReentrantLock和ReadWriteLock读写锁
# Java多线程之ReentrantReadWriteLock源码解析
# Java多线程 ReentrantReadWriteLock原理及实例详解
# 一文了解Java读写锁ReentrantReadWriteLock的使用
# 详解Java ReentrantReadWriteLock读写锁的原理与实现
# Java并发读写锁ReentrantReadWriteLock 使用场景
# 正常运行
# 多个
# 都是
# 死锁
# 有一个
# 有什么
# 随机数
# 是指
# 可以看出
# 顾名思义
# 则可
# 则在
# 可以随时
# 能再
# 绑定
# 抛出
# 小编
# 之重
# 有什么区别
# 图中
相关文章:
如何快速生成高效建站系统源代码?
行程制作网站有哪些,第三方机票电子行程单怎么开?
建站之星代理平台如何选择最佳方案?
Swift开发中switch语句值绑定模式
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
深圳 网站制作,深圳招聘网站哪个比较好一点啊?
上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?
如何基于PHP生成高效IDC网络公司建站源码?
建站168自助建站系统:快速模板定制与SEO优化指南
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
如何在Windows虚拟主机上快速搭建网站?
香港服务器部署网站为何提示未备案?
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
制作电商网页,电商供应链怎么做?
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
免费视频制作网站,更新又快又好的免费电影网站?
,怎么在广州志愿者网站注册?
公司门户网站制作流程,华为官网怎么做?
如何在万网ECS上快速搭建专属网站?
如何选择网络建站服务器?高效建站必看指南
宿州网站制作公司兴策,安徽省低保查询网站?
小型网站建站如何选择虚拟主机?
制作网站外包平台,自动化接单网站有哪些?
制作证书网站有哪些,全国城建培训中心证书查询官网?
制作表格网站有哪些,线上表格怎么弄?
山东云建站价格为何差异显著?
如何批量查询域名的建站时间记录?
制作网站的模板软件,网站怎么建设?
深圳网站制作培训,深圳哪些招聘网站比较好?
建站之星图片链接生成指南:自助建站与智能设计教程
C++中引用和指针有什么区别?(代码说明)
潍坊网站制作公司有哪些,潍坊哪家招聘网站好?
详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
制作网页的网站有哪些,电脑上怎么做网页?
如何在景安云服务器上绑定域名并配置虚拟主机?
网站制作说明怎么写,简述网页设计的流程并说明原因?
西安大型网站制作公司,西安招聘网站最好的是哪个?
深圳网站制作案例,网页的相关名词有哪些?
建站之星如何保障用户数据免受黑客入侵?
如何快速生成ASP一键建站模板并优化安全性?
如何在搬瓦工VPS快速搭建网站?
如何通过商城免费建站系统源码自定义网站主题?
linux top下的 minerd 木马清除方法
开源网站制作软件,开源网站什么意思?
如何快速搭建FTP站点实现文件共享?
建站主机是否属于云主机类型?
建站之星如何修改网站生成路径?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
用v-html解决Vue.js渲染中html标签不被解析的问题
建站之星后台密码遗忘或太弱?如何重置与强化?
*请认真填写需求信息,我们会在24小时内与您取得联系。