- 浏览: 253299 次
- 性别:
- 来自: 沈阳
最新评论
-
wahahachuang8:
GoEasy 实时推送支持IE6-IE11及大多数主流浏览器的 ...
关于服务器推送 -
vfgvfrgvs:
引用引用引用引用引用引用引用引用引用[list][*][lis ...
一个纯java的验证码识别算法 -
656615066lkl:
[color=brown][/color]cczxCZCX
一个纯java的验证码识别算法 -
keephope:
求教一下。是不是这个程序只能分辨出间距相等的验证码的内容呢
一个纯java的验证码识别算法 -
boke_xu:
你好,有关javaocr的问题想请教下你。
打开你的项目,运行 ...
一个纯java的验证码识别算法
2.5. Liveness and Performance(存活性和性能)
In UnsafeCachingFactorizer, we introduced some caching into our factoring servlet in the hope of improving performance. Caching required some shared state, which in turn required synchronization to maintain the integrity of that state. But the way we used synchronization in SynchronizedFactorizer makes it perform badly. The synchronization policy for SynchronizedFactorizer is to guard each state variable with the servlet object's intrinsic lock, and that policy was implemented by synchronizing the entirety of the service method. This simple, coarse-grained approach restored safety, but at a high price.
UnsafeCachingFactorizer类中,为了能够改进性能,我们向因式分解servlet中增加了缓存机制。缓存需要状态共享,这就需要同步机制来维护状态的一致性。但是SynchronizedFactorizer中,我们的同步使用方式导致执行性能很差。SynchronizedFactorizer类的同步策略是使用servlet对象的内在锁来进行同步,并且通过把整个service方法变成同步方法来实现。虽然这样做可以很轻易的就达到实现安全的目标,但却付出了极大的代价。
Because service is synchronized, only one thread may execute it at once. This subverts the intended use of the servlet framework that servlets be able to handle multiple requests simultaneously and can result in frustrated users if the load is high enough. If the servlet is busy factoring a large number, other clients have to wait until the current request is complete before the servlet can start on the new number. If the system has multiple CPUs, processors may remain idle even if the load is high. In any case, even short-running requests, such as those for which the value is cached, may take an unexpectedly long time because they must wait for previous long-running requests to complete.
由于service方法是同步的,在同一个时刻只有一个线程可以执行该方法。这就颠覆了servlet框架推荐的使用方式:可以同时处理多个用户请求。在负载很高情况下,这将导致用户体验极差。如果servlet在忙于分解一个很大的数值的时候,另外一个客户端必须等待,直到分解结束才能开始分解下一个请求。如果系统拥有多个cpu的时候,即使负载很高,处理器也可能会出现空闲状态。即使是很简短的请求,比如那些值已经被缓存的情况下,也会等待很长时间,因为他们必须等待前一个请求被执行结束。
图2.1展示了当多个请求到达同步因数分解servlet的时候会发生什么事情,他们将会排队等待处理时序。我们可以把这个web应用作为差并发性的一个典型例证:能够同时处理请求的数量并不是由硬件资源限制的,而是由软件架构本身限制。幸运的是,通过把同步块变窄可以改善该servlet的并发性能。你要注意不要把同步块的范围变得过窄。你可能不会想把一个本来应该是原子的操作分解到多个同步块中。但是尽量将需要长时间执行的操作从同步块中排除出来是非常合乎情理的。这样一来,其他线程就不会被访问该常运行的线程阻止。
Figure 2.1. Poor Concurrency of SynchronizedFactorizer.
CachedFactorizer in Listing 2.8 restructures the servlet to use two separate synchronized blocks, each limited to a short section of code. One guards the check-then-act sequence that tests whether we can just return the cached result, and the other guards updating both the cached number and the cached factors.
As a bonus, we've reintroduced the hit counter and added a "cache hit" counter as well, updating them within the initial synchronized block. Because these counters constitute shared mutable state as well, we must use synchronization everywhere they are accessed. The portions of code that are outside the synchronized blocks operate exclusively on local (stack-based) variables, which are not shared across threads and therefore do not require synchronization.
Listing 2.8中的CachedFactorizer类把servlet重新用同步块划分。每一个限制到一段很短的代码中。其中一个代码块守护用来判断是否只是需要返回被缓存结果的“check-then-act”时序。而另外一个代码块则是用来更新被缓存的数值和因数。另外,我们重新定义了“点击计数”并且增加了一个“缓存计数”,这两个计数将会在静态初始化块中被初始化。由于这两个计数会建立共享的可变状态,因此在他们被访问的任何地方必须使用同步机制。在同步代码块之外的代码部分只会操作本地变量,这种变量不会被线程间共享,因此不需要同步机制。
Listing 2.8. Servlet that Caches its Last Request and Result.
@ThreadSafe
public class CachedFactorizer implements Servlet {
@GuardedBy("this") private BigInteger lastNumber;
@GuardedBy("this") private BigInteger[] lastFactors;
@GuardedBy("this") private long hits;
@GuardedBy("this") private long cacheHits;
public synchronized long getHits() { return hits; }
public synchronized double getCacheHitRatio() {
return (double) cacheHits / (double) hits;
}
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = null;
synchronized (this) {
++hits;
if (i.equals(lastNumber)) {
++cacheHits;
factors = lastFactors.clone();
}
}
if (factors == null) {
factors = factor(i);
synchronized (this) {
lastNumber = i;
lastFactors = factors.clone();
}
}
encodeIntoResponse(resp, factors);
}
}
CachedFactorizer no longer uses AtomicLong for the hit counter, instead reverting to using a long field. It would be safe to use AtomicLong here, but there is less benefit than there was in CountingFactorizer. Atomic variables are useful for effecting atomic operations on a single variable, but since we are already using synchronized blocks to construct atomic operations, using two different synchronization mechanisms would be confusing and would offer no performance or safety benefit.
CachedFactorizer类不再需要AtomicLong类作为“点击计数”而是采用一个长整型域。这里也可以使用AtomicLong类,但是使用这个类带来的好处没有在CountingFactorizer类中使用这个类明显。Atomic变量类型对于单个变量的原子操作来说是有效率的,但是由于我们已经使用来同步代码块来构建原子请求,那么使用两种同步机制可能会带来不必要的混淆,而不会带来性能和安全性的提高。
The restructuring of CachedFactorizer provides a balance between simplicity (synchronizing the entire method) and concurrency (synchronizing the shortest possible code paths). Acquiring and releasing a lock has some overhead, so it is undesirable to break down synchronized blocks too far (such as factoring ++hits into its own synchronized block), even if this would not compromise atomicity. CachedFactorizer holds the lock when accessing state variables and for the duration of compound actions, but releases it before executing the potentially long-running factorization operation. This preserves thread safety without unduly affecting concurrency; the code paths in each of the synchronized blocks are "short enough".
CachedFactorizer类的重构在并发性和简单性两个方面取得了平衡。请求和释放锁是需要一些负荷的,所以即使不会破坏原子性,也不要把同步块分解的过细。CachedFactorizer类访问状态变量的时候或者访问符合行为的时候会持有锁,会在有可能需要长时间执行的因式分解操作是释放锁。这就在不会影响并发性能的时候保证了线程安全。同步块中的代码长度也就“足够短”了。
Deciding how big or small to make synchronized blocks may require tradeoffs among competing design forces, including safety (which must not be compromised), simplicity, and performance. Sometimes simplicity and performance are at odds with each other, although as CachedFactorizer illustrates, a reasonable balance can usually be found.
具体将同步块变成多长需要在几个同等重要的元素之间:安全、简易性、性能之间作出权衡。尽管可以像CachedFactorizer类中描绘的那样在简易性和性能上可以取得一些平衡但有时候,简易性和性能是不匹配的。
There is frequently a tension between simplicity and performance. When implementing a synchronization policy, resist the temptation to prematurely sacriflce simplicity (potentially compromising safety) for the sake of performance.
简单性和性能上存在某种对立。当实现同步策略的时候,应该避免为了追求性能而牺牲简单性(这有可能会隐藏线程不安全元素)。
Whenever you use locking, you should be aware of what the code in the block is doing and how likely it is to take a long time to execute. Holding a lock for a long time, either because you are doing something compute-intensive or because you execute a potentially blocking operation, introduces the risk of liveness or performance problems.
不管什么时候,如果你需要用到锁,你都应该注意阻塞块中的代码行为以及它们大约的运行时间。不管是在进行集中的计算还是在执行潜在的阻塞操作,长时间的持有锁都会带来存活性和性能问题。
Avoid holding locks during lengthy computations or operations at risk of not completing quickly such as network or console I/O.
应该在网络或者控制台IO过程中,避免长时间的持有锁。
In UnsafeCachingFactorizer, we introduced some caching into our factoring servlet in the hope of improving performance. Caching required some shared state, which in turn required synchronization to maintain the integrity of that state. But the way we used synchronization in SynchronizedFactorizer makes it perform badly. The synchronization policy for SynchronizedFactorizer is to guard each state variable with the servlet object's intrinsic lock, and that policy was implemented by synchronizing the entirety of the service method. This simple, coarse-grained approach restored safety, but at a high price.
UnsafeCachingFactorizer类中,为了能够改进性能,我们向因式分解servlet中增加了缓存机制。缓存需要状态共享,这就需要同步机制来维护状态的一致性。但是SynchronizedFactorizer中,我们的同步使用方式导致执行性能很差。SynchronizedFactorizer类的同步策略是使用servlet对象的内在锁来进行同步,并且通过把整个service方法变成同步方法来实现。虽然这样做可以很轻易的就达到实现安全的目标,但却付出了极大的代价。
Because service is synchronized, only one thread may execute it at once. This subverts the intended use of the servlet framework that servlets be able to handle multiple requests simultaneously and can result in frustrated users if the load is high enough. If the servlet is busy factoring a large number, other clients have to wait until the current request is complete before the servlet can start on the new number. If the system has multiple CPUs, processors may remain idle even if the load is high. In any case, even short-running requests, such as those for which the value is cached, may take an unexpectedly long time because they must wait for previous long-running requests to complete.
由于service方法是同步的,在同一个时刻只有一个线程可以执行该方法。这就颠覆了servlet框架推荐的使用方式:可以同时处理多个用户请求。在负载很高情况下,这将导致用户体验极差。如果servlet在忙于分解一个很大的数值的时候,另外一个客户端必须等待,直到分解结束才能开始分解下一个请求。如果系统拥有多个cpu的时候,即使负载很高,处理器也可能会出现空闲状态。即使是很简短的请求,比如那些值已经被缓存的情况下,也会等待很长时间,因为他们必须等待前一个请求被执行结束。
图2.1展示了当多个请求到达同步因数分解servlet的时候会发生什么事情,他们将会排队等待处理时序。我们可以把这个web应用作为差并发性的一个典型例证:能够同时处理请求的数量并不是由硬件资源限制的,而是由软件架构本身限制。幸运的是,通过把同步块变窄可以改善该servlet的并发性能。你要注意不要把同步块的范围变得过窄。你可能不会想把一个本来应该是原子的操作分解到多个同步块中。但是尽量将需要长时间执行的操作从同步块中排除出来是非常合乎情理的。这样一来,其他线程就不会被访问该常运行的线程阻止。
Figure 2.1. Poor Concurrency of SynchronizedFactorizer.
CachedFactorizer in Listing 2.8 restructures the servlet to use two separate synchronized blocks, each limited to a short section of code. One guards the check-then-act sequence that tests whether we can just return the cached result, and the other guards updating both the cached number and the cached factors.
As a bonus, we've reintroduced the hit counter and added a "cache hit" counter as well, updating them within the initial synchronized block. Because these counters constitute shared mutable state as well, we must use synchronization everywhere they are accessed. The portions of code that are outside the synchronized blocks operate exclusively on local (stack-based) variables, which are not shared across threads and therefore do not require synchronization.
Listing 2.8中的CachedFactorizer类把servlet重新用同步块划分。每一个限制到一段很短的代码中。其中一个代码块守护用来判断是否只是需要返回被缓存结果的“check-then-act”时序。而另外一个代码块则是用来更新被缓存的数值和因数。另外,我们重新定义了“点击计数”并且增加了一个“缓存计数”,这两个计数将会在静态初始化块中被初始化。由于这两个计数会建立共享的可变状态,因此在他们被访问的任何地方必须使用同步机制。在同步代码块之外的代码部分只会操作本地变量,这种变量不会被线程间共享,因此不需要同步机制。
Listing 2.8. Servlet that Caches its Last Request and Result.
@ThreadSafe
public class CachedFactorizer implements Servlet {
@GuardedBy("this") private BigInteger lastNumber;
@GuardedBy("this") private BigInteger[] lastFactors;
@GuardedBy("this") private long hits;
@GuardedBy("this") private long cacheHits;
public synchronized long getHits() { return hits; }
public synchronized double getCacheHitRatio() {
return (double) cacheHits / (double) hits;
}
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = null;
synchronized (this) {
++hits;
if (i.equals(lastNumber)) {
++cacheHits;
factors = lastFactors.clone();
}
}
if (factors == null) {
factors = factor(i);
synchronized (this) {
lastNumber = i;
lastFactors = factors.clone();
}
}
encodeIntoResponse(resp, factors);
}
}
CachedFactorizer no longer uses AtomicLong for the hit counter, instead reverting to using a long field. It would be safe to use AtomicLong here, but there is less benefit than there was in CountingFactorizer. Atomic variables are useful for effecting atomic operations on a single variable, but since we are already using synchronized blocks to construct atomic operations, using two different synchronization mechanisms would be confusing and would offer no performance or safety benefit.
CachedFactorizer类不再需要AtomicLong类作为“点击计数”而是采用一个长整型域。这里也可以使用AtomicLong类,但是使用这个类带来的好处没有在CountingFactorizer类中使用这个类明显。Atomic变量类型对于单个变量的原子操作来说是有效率的,但是由于我们已经使用来同步代码块来构建原子请求,那么使用两种同步机制可能会带来不必要的混淆,而不会带来性能和安全性的提高。
The restructuring of CachedFactorizer provides a balance between simplicity (synchronizing the entire method) and concurrency (synchronizing the shortest possible code paths). Acquiring and releasing a lock has some overhead, so it is undesirable to break down synchronized blocks too far (such as factoring ++hits into its own synchronized block), even if this would not compromise atomicity. CachedFactorizer holds the lock when accessing state variables and for the duration of compound actions, but releases it before executing the potentially long-running factorization operation. This preserves thread safety without unduly affecting concurrency; the code paths in each of the synchronized blocks are "short enough".
CachedFactorizer类的重构在并发性和简单性两个方面取得了平衡。请求和释放锁是需要一些负荷的,所以即使不会破坏原子性,也不要把同步块分解的过细。CachedFactorizer类访问状态变量的时候或者访问符合行为的时候会持有锁,会在有可能需要长时间执行的因式分解操作是释放锁。这就在不会影响并发性能的时候保证了线程安全。同步块中的代码长度也就“足够短”了。
Deciding how big or small to make synchronized blocks may require tradeoffs among competing design forces, including safety (which must not be compromised), simplicity, and performance. Sometimes simplicity and performance are at odds with each other, although as CachedFactorizer illustrates, a reasonable balance can usually be found.
具体将同步块变成多长需要在几个同等重要的元素之间:安全、简易性、性能之间作出权衡。尽管可以像CachedFactorizer类中描绘的那样在简易性和性能上可以取得一些平衡但有时候,简易性和性能是不匹配的。
There is frequently a tension between simplicity and performance. When implementing a synchronization policy, resist the temptation to prematurely sacriflce simplicity (potentially compromising safety) for the sake of performance.
简单性和性能上存在某种对立。当实现同步策略的时候,应该避免为了追求性能而牺牲简单性(这有可能会隐藏线程不安全元素)。
Whenever you use locking, you should be aware of what the code in the block is doing and how likely it is to take a long time to execute. Holding a lock for a long time, either because you are doing something compute-intensive or because you execute a potentially blocking operation, introduces the risk of liveness or performance problems.
不管什么时候,如果你需要用到锁,你都应该注意阻塞块中的代码行为以及它们大约的运行时间。不管是在进行集中的计算还是在执行潜在的阻塞操作,长时间的持有锁都会带来存活性和性能问题。
Avoid holding locks during lengthy computations or operations at risk of not completing quickly such as network or console I/O.
应该在网络或者控制台IO过程中,避免长时间的持有锁。
发表评论
-
使用commons-fileupload实现单个和多个文件上传
2013-06-24 16:19 914见如下: http://www.blogjava.net/s ... -
pgpool-I I的recovery
2013-06-06 19:51 945pgpool-I I のオンラインリカバリの概要 -
ウェブサーバの 暗号アルゴリズムの選び方
2013-03-26 10:59 975日语的一份关于ssl的加密算法的文档,有时间的话需要研究一下。 ... -
struts2 best practice-Why we need a framework.
2012-12-03 16:28 1018A web application framework is ... -
struts2 best practice-Use empty action components to forward to your results
2012-11-29 12:25 899Use empty action components to ... -
struts2中inceptor的执行顺序
2012-08-15 17:27 1034struts2中的inceptor是可以指定执行顺序的。 具 ... -
漫谈HTTPS(挖坑待填)
2012-04-23 09:13 1044漫谈HTTPS(挖坑待填) -
Java序列化之四: 进一步思考
2012-04-20 10:24 9761,当需要被序列化的类对象中的一部分成员变量是不可被序列化的, ... -
Java序列化之三: 常见实例分析
2012-04-20 10:20 15561,HTTPSession与Serializale ... -
Java序列化之二: 从代码开始
2012-04-19 14:20 12831,最简单,最典型的序列化代码。 附录1中给出的JAV ... -
Java序列化之一: 什么是JAVA序列化
2012-04-19 14:03 1969这几天受领导委托,做 ... -
一个纯java的验证码识别算法
2012-04-05 08:45 33293在进行性能测试时,某些时候需要输入验证码。手工输入是不可能的, ... -
連載二、Servlet 3.0の6つのEase of Development
2011-07-22 14:16 818Servlet 3.0では、EoDとして「Annotation ... -
連載一、Servlet 3.0の6つの主な変更点
2011-07-22 14:00 819Tomcat 7では、Tomcat 6に対して実装するサーブレ ... -
連載二、クロスサイトスクリプティング基本
2011-07-13 10:01 722XSSセキュリティホールによる起こり得る被害 ●cookie ... -
qmailによるSMTPサーバの構築
2011-06-15 14:41 12311、qmailの仕組み a、sendmailが、メッセー ... -
LDAP SCHEMA DESIGN(三)
2010-11-05 11:34 13373.2 Do not modify the standard ... -
LDAP SCHEMA DESIGN(二)
2010-11-04 09:42 12732 Requirements When considerin ... -
LDAP SCHEMA DESIGN_Synopsis (大纲)
2010-11-02 16:55 1490Synopsis (大纲) ... -
Chapter 4. Composing Objects(合成对象)
2010-01-13 11:02 1055Chapter 4. Composing Objects(组合 ...
相关推荐
在计算机科学领域,特别是软件工程与系统验证方面,**活动性(Liveness)**和**安全性(Safety)属性**是两个核心概念,用于描述系统的行为特性。这两种属性对于确保系统的正确性和可靠性至关重要。本文将基于提供的...
这项技术通过评估两个数据集的性能来展示其有效性:一个是由120名参与者、15个播放设备和12个录音设备生成的255,173个声音样本,另一个是由42名参与者、26个播放设备和25个录音设备生成的18,030个公开可用的声音样本...
传统的头部检测方法通常依赖于形状和颜色特征,然而这些特征对于照片、模仿面具以及商场中的人体模型来说非常相似,从而导致了误检的可能性增加。因此,需要一种更加有效的后处理步骤——即人脸活性检测方法——来...
[root@k8s-master01 k8s-test]# cat livenessProbe-tcp.yaml apiVersion: v1 kind: Pod metadata: name: liveness-tcp namespace: default spec: containers: - name: liveness-tcp-container image: kone....
它提供了对Android API的兼容性支持,同时引入了许多新特性和改进,让开发者能更好地掌控项目的架构和性能。AndroidX库包含了许多用于UI、数据存储、测试等方面的功能模块,而活体检测正是其中的一个重要组成部分。 ...
[root@k8s-master01 k8s-test]# cat liveness.yaml apiVersion: v1 kind: Pod metadata: name: liveness-exec-pod namespace: default spec: containers: - name: liveness-exec-container image: kone....
Hadoop是一个开源的分布式存储和计算框架,它允许用户存储大量数据并进行分布式计算。Hadoop 2.9.0版本中的YARN(Yet ...配置YARN的属性集是实现这些目标的基础工作,对于Hadoop集群的性能和安全性有着直接的影响。
本压缩包“Liveness-Detection(android.support) (1).zip”提供了一个高级的活体检测Android SDK,版本号为V1.3.3,它专门设计来增强应用程序的安全性和用户体验。 SDK(Software Development Kit)是软件开发者...
Python的易读性和广泛支持使得这个API易于理解和扩展。 3. **Django REST框架** Django是Python的一款流行Web开发框架,而REST(Representational State Transfer)是一种网络应用程序的设计风格,常用于构建可...
《人脸活体检测技术详解与应用》 在现代信息技术领域,人脸识别技术已经广泛应用于安全监控、身份...通过深入理解和运用其中的算法,我们可以更好地应对现实世界中的安全挑战,提升人工智能系统的智能水平和可靠性。
由于面部信息在身份验证和识别中的流行,生物识别领域已经成为计算机视觉研究中最活跃和最具挑战性的领域之一。尽管人脸识别技术在过去几十年中取得了显著进步,但不同视角、主体老化以及复杂户外照明等问题仍然是...
在计算机视觉领域,图像处理和生物识别技术是至关重要的部分,而“局部对比相位描述符”(Local Contrast Phase Descriptor,简称LCPD)正是其中的一种创新方法,尤其在活体检测(liveness detection)中表现出色。...
Scalability and Performance Small Details Matter eBay Search Index Compression TOME Combat Server Measurement and Distributions How to Scale - Scaling DevOps Automate Everything Autoscaling App Engine...
Kubernetes Liveness 和 Readiness Probes 作为 Elixir Plugs。 安装 可以通过将healthchex添加到中的依赖项列表来安装该软件包: def deps do [ { :healthchex , " ~> 0.2 " } ] end 用法 为了使文档保持最新...
内部排序:如果整个排序过程不需要借助外部存储器(如磁盘等),所有排序操作都是在内存中完成,这种排序就被称为内部排序。 就常用的内部排序算法来说,可以分为以下几类: * 选择排序(直接选择排序,堆排序) ...
业务流程的安全行为特性,例如数据活跃性(data-liveness)和数据界限性(data-boundedness),在电子商务业务流程中尤为重要。数据活跃性涉及到数据项在业务流程中是否能够持续得到处理和更新;而数据界限性则关注...
2. Kubernetes的探测机制:Kubernetes扩展了健康检查的概念,包括就绪探针(readiness probe)和存活探针(liveness probe)。就绪探针确保容器已准备好接收流量,而存活探针则用于确定何时重启不健康的容器。这些...
The main goal of this document is to outline best practices for optimizing performance, resource usage, and perceived user experience in MIDP applications. By following these guidelines, developers ...
鲜活AWS Liveness工具。安装 npm i --save aws-liveness用法 const AWSLiveness = require ( 'aws-liveness' ) ;const { DynamoDB } = require ( 'aws-sdk' ) ;const awsLiveness = new AWSLiveness ( ) ;const ...