网站设计师是什么连云港网站优化方案

web/2025/10/8 15:53:15/文章来源:
网站设计师是什么,连云港网站优化方案,wordpress4.0友情链接,乐清网站设计哪家好转载自 Java中的读/写锁 原文链接 作者#xff1a;Jakob Jenkov 译者#xff1a;微凉 校对#xff1a;丁一 相比Java中的锁(Locks in Java)里Lock实现#xff0c;读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作#xff0c;且写操作没有读操作那么频…转载自  Java中的读/写锁 原文链接 作者Jakob Jenkov 译者微凉 校对丁一 相比Java中的锁(Locks in Java)里Lock实现读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作且写操作没有读操作那么频繁。在没有写操作的时候两个线程同时读一个资源没有任何问题所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源就不应该再有其它线程对该资源进行读或写译者注也就是说读-读能共存读-写不能共存写-写不能共存。这就需要一个读/写锁来解决这个问题。 Java5在java.util.concurrent包中已经包含了读写锁。尽管如此我们还是应该了解其实现背后的原理。 以下是本文的主题 读/写锁的Java实现(Read / Write Lock Java Implementation)读/写锁的重入(Read / Write Lock Reentrance)读锁重入(Read Reentrance)写锁重入(Write Reentrance)读锁升级到写锁(Read to Write Reentrance)写锁降级到读锁(Write to Read Reentrance)可重入的ReadWriteLock的完整实现(Fully Reentrant ReadWriteLock)在finally中调用unlock() (Calling unlock() from a finally-clause)读/写锁的Java实现 先让我们对读写访问资源的条件做个概述 读取 没有线程正在做写操作且没有线程在请求写操作。 写入 没有线程正在做读写操作。 如果某个线程想要读取资源只要没有线程正在对该资源进行写操作且没有线程请求对该资源的写操作即可。我们假设对写操作的请求比对读操作的请求更重要就要提升写请求的优先级。此外如果读操作发生的比较频繁我们又没有提升写操作的优先级那么就会产生“饥饿”现象。请求写操作的线程会一直阻塞直到所有的读线程都从ReadWriteLock上解锁了。如果一直保证新线程的读操作权限那么等待写操作的线程就会一直阻塞下去结果就是发生“饥饿”。因此只有当没有线程正在锁住ReadWriteLock进行写操作且没有线程请求该锁准备执行写操作时才能保证读操作继续。 当其它线程没有对共享资源进行读操作或者写操作时某个线程就有可能获得该共享资源的写锁进而对共享资源进行写操作。有多少线程请求了写锁以及以何种顺序请求写锁并不重要除非你想保证写锁请求的公平性。 按照上面的叙述简单的实现出一个读/写锁代码如下 public class ReadWriteLock{private int readers 0;private int writers 0;private int writeRequests 0;public synchronized void lockRead() throws InterruptedException{while(writers 0 || writeRequests 0){wait();}readers;}public synchronized void unlockRead(){readers--;notifyAll();}public synchronized void lockWrite() throws InterruptedException{writeRequests;while(readers 0 || writers 0){wait();}writeRequests--;writers;}public synchronized void unlockWrite() throws InterruptedException{writers--;notifyAll();} } ReadWriteLock类中读锁和写锁各有一个获取锁和释放锁的方法。 读锁的实现在lockRead()中,只要没有线程拥有写锁writers0且没有线程在请求写锁writeRequests 0所有想获得读锁的线程都能成功获取。 写锁的实现在lockWrite()中,当一个线程想获得写锁的时候首先会把写锁请求数加1writeRequests然后再去判断是否能够真能获得写锁当没有线程持有读锁readers0 ,且没有线程持有写锁writers0时就能获得写锁。有多少线程在请求写锁并无关系。 需要注意的是在两个释放锁的方法unlockReadunlockWrite中都调用了notifyAll方法而不是notify。要解释这个原因我们可以想象下面一种情形 如果有线程在等待获取读锁同时又有线程在等待获取写锁。如果这时其中一个等待读锁的线程被notify方法唤醒但因为此时仍有请求写锁的线程存在writeRequests0所以被唤醒的线程会再次进入阻塞状态。然而等待写锁的线程一个也没被唤醒就像什么也没发生过一样译者注信号丢失现象。如果用的是notifyAll方法所有的线程都会被唤醒然后判断能否获得其请求的锁。 用notifyAll还有一个好处。如果有多个读线程在等待读锁且没有线程在等待写锁时调用unlockWrite()后所有等待读锁的线程都能立马成功获取读锁 —— 而不是一次只允许一个。 读/写锁的重入 上面实现的读/写锁(ReadWriteLock) 是不可重入的当一个已经持有写锁的线程再次请求写锁时就会被阻塞。原因是已经有一个写线程了——就是它自己。此外考虑下面的例子 Thread 1 获得了读锁Thread 2 请求写锁但因为Thread 1 持有了读锁所以写锁请求被阻塞。Thread 1 再想请求一次读锁但因为Thread 2处于请求写锁的状态所以想再次获取读锁也会被阻塞。 上面这种情形使用前面的ReadWriteLock就会被锁定——一种类似于死锁的情形。不会再有线程能够成功获取读锁或写锁了。 为了让ReadWriteLock可重入需要对它做一些改进。下面会分别处理读锁的重入和写锁的重入。 读锁重入 为了让ReadWriteLock的读锁可重入我们要先为读锁重入建立规则 要保证某个线程中的读锁可重入要么满足获取读锁的条件没有写或写请求要么已经持有读锁不管是否有写请求。 要确定一个线程是否已经持有读锁可以用一个map来存储已经持有读锁的线程以及对应线程获取读锁的次数当需要判断某个线程能否获得读锁时就利用map中存储的数据进行判断。下面是方法lockRead和unlockRead修改后的的代码 public class ReadWriteLock{private MapThread, Integer readingThreads new HashMapThread, Integer();private int writers 0;private int writeRequests 0;public synchronized void lockRead() throws InterruptedException{Thread callingThread Thread.currentThread();while(! canGrantReadAccess(callingThread)){wait(); }readingThreads.put(callingThread,(getAccessCount(callingThread) 1));}public synchronized void unlockRead(){Thread callingThread Thread.currentThread();int accessCount getAccessCount(callingThread);if(accessCount 1) { readingThreads.remove(callingThread); } else {readingThreads.put(callingThread, (accessCount -1)); }notifyAll();}private boolean canGrantReadAccess(Thread callingThread){if(writers 0) return false;if(isReader(callingThread) return true;if(writeRequests 0) return false;return true;}private int getReadAccessCount(Thread callingThread){Integer accessCount readingThreads.get(callingThread);if(accessCount null) return 0;return accessCount.intValue();}private boolean isReader(Thread callingThread){return readingThreads.get(callingThread) ! null;} } 代码中我们可以看到只有在没有线程拥有写锁的情况下才允许读锁的重入。此外重入的读锁比写锁优先级高。 写锁重入 仅当一个线程已经持有写锁才允许写锁重入再次获得写锁。下面是方法lockWrite和unlockWrite修改后的的代码。 public class ReadWriteLock{private MapThread, Integer readingThreads new HashMapThread, Integer();private int writers 0;private int writeRequests 0;public synchronized void lockRead() throws InterruptedException{Thread callingThread Thread.currentThread();while(! canGrantReadAccess(callingThread)){wait(); }readingThreads.put(callingThread,(getAccessCount(callingThread) 1));}public synchronized void unlockRead(){Thread callingThread Thread.currentThread();int accessCount getAccessCount(callingThread);if(accessCount 1) { readingThreads.remove(callingThread); } else {readingThreads.put(callingThread, (accessCount -1)); }notifyAll();}private boolean canGrantReadAccess(Thread callingThread){if(writers 0) return false;if(isReader(callingThread) return true;if(writeRequests 0) return false;return true;}private int getReadAccessCount(Thread callingThread){Integer accessCount readingThreads.get(callingThread);if(accessCount null) return 0;return accessCount.intValue();}private boolean isReader(Thread callingThread){return readingThreads.get(callingThread) ! null;} } 注意在确定当前线程是否能够获取写锁的时候是如何处理的。 读锁升级到写锁 有时我们希望一个拥有读锁的线程也能获得写锁。想要允许这样的操作要求这个线程是唯一一个拥有读锁的线程。writeLock()需要做点改动来达到这个目的 public class ReadWriteLock{private MapThread, Integer readingThreads new HashMapThread, Integer();private int writeAccesses 0;private int writeRequests 0;private Thread writingThread null;public synchronized void lockWrite() throws InterruptedException{writeRequests;Thread callingThread Thread.currentThread();while(!canGrantWriteAccess(callingThread)){wait();}writeRequests--;writeAccesses;writingThread callingThread;}public synchronized void unlockWrite() throws InterruptedException{writeAccesses--;if(writeAccesses 0){writingThread null;}notifyAll();}private boolean canGrantWriteAccess(Thread callingThread){if(isOnlyReader(callingThread)) return true;if(hasReaders()) return false;if(writingThread null) return true;if(!isWriter(callingThread)) return false;return true;}private boolean hasReaders(){return readingThreads.size() 0;}private boolean isWriter(Thread callingThread){return writingThread callingThread;}private boolean isOnlyReader(Thread thread){return readers 1 readingThreads.get(callingThread) ! null;} } 现在ReadWriteLock类就可以从读锁升级到写锁了。 写锁降级到读锁 有时拥有写锁的线程也希望得到读锁。如果一个线程拥有了写锁那么自然其它线程是不可能拥有读锁或写锁了。所以对于一个拥有写锁的线程再获得读锁是不会有什么危险的。我们仅仅需要对上面canGrantReadAccess方法进行简单地修改 public class ReadWriteLock{private boolean canGrantReadAccess(Thread callingThread){if(isWriter(callingThread)) return true;if(writingThread ! null) return false;if(isReader(callingThread) return true;if(writeRequests 0) return false;return true;} } 可重入的ReadWriteLock的完整实现 下面是完整的ReadWriteLock实现。为了便于代码的阅读与理解简单对上面的代码做了重构。重构后的代码如下。 public class ReadWriteLock{private MapThread, Integer readingThreads new HashMapThread, Integer();private int writeAccesses 0;private int writeRequests 0;private Thread writingThread null;public synchronized void lockRead() throws InterruptedException{Thread callingThread Thread.currentThread();while(! canGrantReadAccess(callingThread)){wait();}readingThreads.put(callingThread,(getReadAccessCount(callingThread) 1));}private boolean canGrantReadAccess(Thread callingThread){if(isWriter(callingThread)) return true;if(hasWriter()) return false;if(isReader(callingThread)) return true;if(hasWriteRequests()) return false;return true;}public synchronized void unlockRead(){Thread callingThread Thread.currentThread();if(!isReader(callingThread)){throw new IllegalMonitorStateException(Calling Thread does not hold a read lock on this ReadWriteLock);}int accessCount getReadAccessCount(callingThread);if(accessCount 1){ readingThreads.remove(callingThread); } else { readingThreads.put(callingThread, (accessCount -1));}notifyAll();}public synchronized void lockWrite() throws InterruptedException{writeRequests;Thread callingThread Thread.currentThread();while(!canGrantWriteAccess(callingThread)){wait();}writeRequests--;writeAccesses;writingThread callingThread;}public synchronized void unlockWrite() throws InterruptedException{if(!isWriter(Thread.currentThread()){throw new IllegalMonitorStateException(Calling Thread does not hold the write lock on this ReadWriteLock);}writeAccesses--;if(writeAccesses 0){writingThread null;}notifyAll();}private boolean canGrantWriteAccess(Thread callingThread){if(isOnlyReader(callingThread)) return true;if(hasReaders()) return false;if(writingThread null) return true;if(!isWriter(callingThread)) return false;return true;}private int getReadAccessCount(Thread callingThread){Integer accessCount readingThreads.get(callingThread);if(accessCount null) return 0;return accessCount.intValue();}private boolean hasReaders(){return readingThreads.size() 0;}private boolean isReader(Thread callingThread){return readingThreads.get(callingThread) ! null;}private boolean isOnlyReader(Thread callingThread){return readingThreads.size() 1 readingThreads.get(callingThread) ! null;}private boolean hasWriter(){return writingThread ! null;}private boolean isWriter(Thread callingThread){return writingThread callingThread;}private boolean hasWriteRequests(){return this.writeRequests 0;} } 在finally中调用unlock() 在利用ReadWriteLock来保护临界区时如果临界区可能抛出异常在finally块中调用readUnlock()和writeUnlock()就显得很重要了。这样做是为了保证ReadWriteLock能被成功解锁然后其它线程可以请求到该锁。这里有个例子 lock.lockWrite(); try{//do critical section code, which may throw exception } finally {lock.unlockWrite(); } 上面这样的代码结构能够保证临界区中抛出异常时ReadWriteLock也会被释放。如果unlockWrite方法不是在finally块中调用的当临界区抛出了异常时ReadWriteLock 会一直保持在写锁定状态就会导致所有调用lockRead()或lockWrite()的线程一直阻塞。唯一能够重新解锁ReadWriteLock的因素可能就是ReadWriteLock是可重入的当抛出异常时这个线程后续还可以成功获取这把锁然后执行临界区以及再次调用unlockWrite()这就会再次释放ReadWriteLock。但是如果该线程后续不再获取这把锁了呢所以在finally中调用unlockWrite对写出健壮代码是很重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/89131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电影网站可以备案吗南宁工程建设信息网

目录 概念 硬盘的分区 实操 创建分区 fdisk&#xff08;<2T&#xff09; 创建文件系统 挂载 自动挂载&#xff08;永久挂载&#xff09; gpt区分 swap 交换分区 如何删除已挂载的分区 概念 硬盘&#xff1a;计算机的存储设备。&#xff08;如无特殊说明&#xff0…

win2008 iis7发布网站阿里云网站备份

多线程 程序、进程、线程的概念 程序&#xff1a;是指令和数据的有序集合&#xff0c;是一个静态的概念。比如&#xff0c;在电脑中&#xff0c;打开某个软件&#xff0c;就是启动程序。 进程&#xff1a;是执行程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;…

做内贸什么网站资源比较多晒豆网站建设

教育 -森林植物识别技术 ——珍稀植物识别-章节资料考试资料-南京森林警察学院【】 单元测试一 1、【多选题】根据《最高人民法院关于审理破坏森林资源刑事案件具体应用法律若干问题的解释》规定&#xff0c;珍贵树木包括 A、列入《野生药材资源保护管理条例》中的植物 B、列入…

网站优化大赛陕西省建设厅便民服务网站

在MES项目实施过程中,经常会碰到工控机和电脑的选型问题,那么他们的区别是什么? 1、控机和普通个人电脑(PC)相比,具有以下几个区别: 1.运行环境不同:工控机通常需要在各种恶劣的工业环境中运行,如高温、高湿、强电磁干扰等,因此需要具有防尘、防水、抗干扰等特点。而…

新建的网站 找不到了开一个网站需要多少钱

Hudi&#xff0c;这个近年来备受瞩目的数据存储解决方案&#xff0c;无疑是大数据领域的一颗耀眼新星。其凭借出色的性能和稳定性&#xff0c;以及对于数据湖场景的深度适配&#xff0c;赢得了众多企业和开发者的青睐。然而&#xff0c;正如任何一项新兴技术&#xff0c;Hudi在…

谷歌在线搜索免费seo教程资源

1.判断有无注入点; and 11 and 12 2.猜表一般的表的名称无非是admin adminuser user pass password 等..and 0<>(select count(*) from *)and 0<>(select count(*) from admin) ---判断是否存在admin这张表3.猜帐号数目 如果遇到0< 返回正确页面 1<返回错误页…

中国网站设计公司网站首页轮播图怎么做

Unix网络编程是针对类Unix操作系统&#xff08;包括Linux、BSD以及其他遵循POSIX标准的操作系统&#xff09;进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中&#xff0c;网络编程通常涉及到以…

企业网站系统的设计与开发怎样在网上卖东西步骤

Hello&#xff0c;我是小恒不会java 最近学习django&#xff0c;写了一个demo,学到了不少东西。 我在GitHub上开源了&#xff0c;提示‘自行查看代码&#xff0c;维护&#xff0c;运行’。 最近有事&#xff0c;先发布代码了&#xff0c;我就随缘维护更新吧 介绍&#xff1a; 定…

怎么给网站做开场动画宁波企业制作网站

在数字化时代&#xff0c;信息的快速获取和高效整理变得尤为重要。微信公众号作为信息传播的重要平台&#xff0c;其内容经常需要被转换成更易于编辑和存档的格式&#xff0c;如Word文档。这里&#xff0c;我们将介绍如何利用“微附件”小程序实现这一过程&#xff0c;并分享一…

烟台网站搜索优化想买手表在哪个网站买是正品

诸多预测认为&#xff0c;2024 年将成为国内大模型产业应用爆发的元年。中关村科金作为领先的对话式 AI 技术解决方案提供商&#xff0c;自主研发的智能陪练产品&#xff0c;以学、练、考、培一体化的方式&#xff0c;为企业提供全方位的综合培训服务。 借助大模型技术方面的突…

公司设计网站多少钱电商运营推广怎么做

jboss8日志级别设置是否在寻找一种简单的方法来宣传&#xff0c;展示或演示使用JBoss业务规则管理系统&#xff08;BRMS&#xff09;产品的入门难度&#xff1f; 别无所求&#xff0c;因为我们已经召集了这个研讨会&#xff0c;因此您可以围绕JBoss BRMS构建一个晚上&#xff…

重庆招聘网官方网站大庆做网站比较好的公司

iPhone 拥有巨大的存储容量。您可以在 iPhone 设备上存储图像、文档和视频等数据。有时&#xff0c;您的 iPhone 会发生许多意外事件&#xff0c;例如意外删除&#xff0c;从而导致数据丢失。这里有 11 个最好的免费 iPhone 数据恢复软件&#xff0c;您可以免费下载&#xff0c…

求个没封的w站2022wordpress手机页面底部导航

一、工厂方法模式&#xff08;Factory Method&#xff09; 工厂方法模式有三种 1、普通工厂模式&#xff1a;就是建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。首先看下关系图&#xff1a; 举例如下&#xff1a;&#xff08;我们举一个发送邮件和短信的…

苏州网站建设制作工作室成都关键词

boot程序的主要功能是引导vxworks 内核,所以boot程序需要知道vxworks的内核存放在何处&#xff0c;通过什么手段去获取。在vxworks缺省的boot程序里有一条内建的default boot line,它指明了获得vxworks内核的途径&#xff0c;在boot程序启动时&#xff0c;它先寻找NVRAM里面有无…

商业网站开发模式外贸公司取名字参考大全

用途 字符匹配 语法 常用元字符 []    区间范围框 枚举值  [a-z0-9A-Z_] |    分枝条件或 \    特殊转义符&#xff08;取消转义&#xff09; \W [^A-Za-z0-9_] [\r\n] 换行符匹配 [\u4e00-\u9fa5] 汉字 [\s\S] 任意字符 限定符 贪婪匹配&…

网站安全狗卸载卸载不掉网页与网站设计

简介 在HTTP协议中&#xff0c;与get请求把请求参数直接放在url中不同&#xff0c;post请求的请求数据需通过消息主体(request body)中传递。 且协议中并没有规定post请求的请求数据必须使用什么样的编码方式&#xff0c;所以其请求数据可以有不同的编码方式&#xff0c;服务…

外国做动漫图片的网站叫什么潮汕网站建设

1. 前言 本文的目的&#xff0c;是帮助大家快速理解掌握Backbone的使用&#xff0c;但它并不是API&#xff0c;因此我不会将每一个方法都详细地描述&#xff0c;但是我会告诉你如何学习它们。 这是一篇稍稍较长的技术文章&#xff0c;因为我想将我所了解的东西尽可能详细地分享…

知名的网站建设公司杭州网络公司有哪些

摘要 二十一世纪是信息技术的时代,计算机已经应用到了各行各业中。采用计算机信息管理技术,可以有效的降低企业的管理成本,提高企业内部的工作效率。 本文从天天宾馆客房客房管理的一般流程出发,设计了一套天天宾馆客房管理信息系统,它可以管理天天宾馆客房中所有的客房的…

怎么登录百度app响应式网站做seo怎么样

文章目录 正则表达式概述使用场景不同环境下的正则表达式范例Linux (使用grep命令)Java (使用Pattern和Matcher类)Python (使用re模块) 正则表达式概述 正则表达式&#xff08;Regular Expression&#xff0c;简称regex或regexp&#xff09;是一种强大的文本处理工具&#xff…

做淘宝首页初学ps视频网站免费域名查询

以下源码基于rocketmq-spring-boot-start 2.1.1版本&#xff0c;其它版本可能会有差异 一. 前言 当我们在Spring Boot项目中集成RocketMQ后&#xff0c;只需要在配置文件(application.yml)中添加rocketmq的相关配置&#xff0c;即可使用rocketMQTemplate发送对象消息。登录Ro…