Java 并发编程之测试(三)

产生更多的交替操作

由于并发代码中发生的错误一般都是低概率事件,所以在测试并发错误时需要反复地执行许多次,但有些方法可以提高发现这些错误的概率 ,在前面提到过,在多处理器系统上,如果 处理器的数量少于活动线程的数量,那么 与单处理器的系统 或者 包含多个处理器的系统相比,将能产生更多的交替行为。

有一种有用的方法能提高交替操作的数量。以便能更有效的搜索程序的状态空间:就是在访问状态的操作中加上Thread.yield作为一个空操作。当代码在访问状态的时候没有使用足够的同步,将存在一些对执行时序敏感的错误,通过在某个操作的执行过程 中调用yield方法,可以将这些错误暴露出来。这种方法需要在测试 中添加一些调用并且在正式产品吕删除这些调用 。

	public synchronized void tranferCredits(Account from,Account to,int amount) {
		from.setBalance(from.getBalance()-amount);
		if (random.nextInt(1000)>THRESHOLD) {
			Thread.yield();
		}
		to.setBalance(to.getBalance()+amount);
	}

性能测试

性能测试要符合当前程序的应用场景,理想情况下应该反映出被测试对象的在应用程序中的实际用法。

第二个目标就是根据经验值来调整各种不同的限值,例如线程数量,缓存容量等等,这些限值都依赖于平台特性,我们通常要合理的选择这些值,使程序能够在更多的系统上良好的运行。

多种算法的比较

测试结果表明,LinkedBlockgingQueue的可伸缩性要高于ArrayBlockingQueue,初看起来这个结果似乎有些奇怪,链表队列在每次插入元素时,都必须分配一个链表节点对象 ,这似乎比基于数组的队列相比,链表队列的put和take等方法支持并发性更高的访问,因为一些优化后的链接队列算法能将队列头节点的更新 操作与尾节点的更新操作分享开来。因此如果算法能通过多执行一些内存分配操作来降低竞争 程度,那么这种算法通常具有更高的可伸缩性。

时间: 2024-08-26 14:28:47

Java 并发编程之测试(三)的相关文章

Java 并发编程之测试

并发程序测试的要点 吞吐量 响应性 可伸缩性 正确性测试 首先需要一个可供测试的程序做为栗子.就是下面这个了.一个固定长度的 队列,其中定义可阻塞的put和take方法,并通过两个计数器进行控制. import java.util.concurrent.Semaphore; public class BoundedBuffer<E> { private final Semaphore availableItems, availableSpaces; private final E[] Item

JAVA并发编程实战---第三章:对象的共享(2)

线程封闭 如果仅仅在单线程内访问数据,就不需要同步,这种技术被称为线程封闭,它是实现线程安全性的最简单的方式之一.当某个对象封闭在一个线程中时,这种方法将自动实现线程安全性,即使被封闭的对象本生不是线程安全的. 实现好的并发是一件困难的事情,所以很多时候我们都想躲避并发.避免并发最简单的方法就是线程封闭.什么是线程封闭呢? 就是把对象封装到一个线程里,只有这一个线程能看到此对象.那么这个对象就算不是线程安全的也不会出现任何安全问题.实现线程封闭有哪些方法呢? 1:ad-hoc线程封闭 这是完全靠

Java 并发编程之测试(二)

资源管理的测试 先摆上昨天测试用的栗子 import java.util.concurrent.Semaphore; public class BoundedBuffer<E> { private final Semaphore availableItems, availableSpaces; private final E[] Items; private int putPosition = 0, takePosition = 0; public BoundedBuffer(int capa

JAVA并发编程实战---第三章:对象的共享

在没有同步的情况下,编译器.处理器以及运行时等都可能对操作的执行顺序进行一些意想不到的调整.在缺乏足够同步的多线程程序中,要对内存操作的执行顺序进行判断几乎无法得到正确的结果. 非原子的64位操作 当线程在没有同步的情况下读取变量时,可能会读到一个失效值,但至少这个值是由之前的某个线程设置,而不是一个随机值.这种安全性保证也被称为最低安全性. Java内存模型要求:变量的读取操作和写入操作都必须是原子操作,但对于非Volatile类型的long和Double变量,JVM允许将64的读操作或写操作

Java并发编程系列(三)-locks锁机制类

Java中的锁可以分为"同步锁"和JUC包里面的锁(locks包) 同步锁:即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁.Java 1.0版本中就已经支持同步锁了.同步锁的原理是,对于每一个对象,有且仅有一个同步锁:不同的线程能共同访问该同步锁.但是,在同一个时间点,该同步锁能且只能被一个线程获取到.这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行:而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行. locks包:相

Java并发编程的艺术(六)——线程间的通信

多条线程之间有时需要数据交互,下面介绍五种线程间数据交互的方式,他们的使用场景各有不同. 1. volatile.synchronized关键字 PS:关于volatile的详细介绍请移步至:Java并发编程的艺术(三)--volatile 1.1 如何实现通信? 这两种方式都采用了同步机制实现多条线程间的数据通信.与其说是"通信",倒不如说是"共享变量"来的恰当.当一个共享变量被volatile修饰 或 被同步块包裹后,他们的读写操作都会直接操作共享内存,从而各个

【Java并发编程实战】—– AQS(三):阻塞、唤醒:LockSupport

在上篇博客([Java并发编程实战]-– AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 lock方法,在调用acquireQueued(): if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; 在acquireQueued()中调用parkAndCheckIn

【Java并发编程】6、volatile关键字解析&amp;内存模型&amp;并发编程中三概念

转自:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来

《Java并发编程实战》第三章 对象的共享 读书笔记

一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见性的描写叙述即多线程能够实时获取其它线程改动后的状态. *** 待补充   两个工人同一时候记录生产产品总数问题 1. 失效数据 可见性出现故障就是其它线程没有获取到改动后的状态,更直观的描写叙述就是其它线程获取到的数据是失效数据. 2. 非原子64位操作 3. 加锁与可见性 比如在一个变量的读取与