Java理论与实践: 流行的原子 - 编程入门网
ronized void acquire() throws InterruptedException {
if (Thread.interrupted()) throw new InterruptedException ();
while (curOwner != null)
wait();
curOwner = Thread.currentThread();
}
public synchronized void release() {
if (curOwner == Thread.currentThread()) {
curOwner = null;
notify();
} else
throw new IllegalStateException("not owner of mutex");
}
}
清单 1 中的计数器类可以可靠地工作,在竞争很小或没有竞争时都可以很好 地执行。然而,在竞争激烈时,这将大大损害性能,因为 JVM 用了更多的时间 来调度线程,管理竞争和等待线程队列,而实际工作(如增加计数器)的时间却 很少。您可以回想 上月专栏中的图,该图显示了一旦多个线程使用同步竞争一 个内置监视器,吞吐量将如何大幅度下降。虽然该专栏说明了新的 ReentrantLock 类如何可以更可伸缩地替代同步,但是对于一些问题,还有更好 的解决方法。 Java理论与实践: 流行的原子(2)时间:2010-12-22 IBM Brian Goetz锁定问题 使用锁定,如果一个线程试图获取其他线程已经具有的锁定,那么该线程将 被阻塞,直到该锁定可用。此方法具有一些明显的缺点,其中包括当线程被阻塞 来等待锁定时,它无法进行其他任何操作。如果阻塞的线程是高优先级的任务, 那么该方案可能造成非常不好的结果(称为 优先级倒置的危险)。 使用锁定还有一些其他危险,如死锁(当以不一致的顺序获得多个锁定时会 发生死锁)。甚至没有这种危险,锁定也仅是相对的粗粒度协调机制,同样非常 适合管理简单操作,如增加计数器或更新互斥拥有者。如果有更细粒度的机制来 可靠管理对单独变量的并发更新,则会更好一些;在大多数现代处理器都有这种 机制。 硬件同步原语 如前所述,大多数现代处理器都包含对多处理的支持。当然这种支持包括多 处理器可以共享外部设备和主内存,同时它通常还包括对指令系统的增加来支持 多处理的特殊要求。特别是,几乎每个现代处理器都有通过可以检测或阻止其他 处理器的并发访问的方式来更新共享变量的指令。 比较并交换 (CAS) 支持并发的第一个处理器提供原子的测试并设置操作,通常在单位上运行这 项操作。现在的处理器(包括 Intel 和 Sparc 处理器)使用的最通用的方法是 实现名为 比较并转换或 CAS 的原语。(在 Intel 处理器中,比较并交换通过 指令的 cmpxchg 系列实现。PowerPC 处理器有一对名为“加载并保留”和“条 件存储”的指令,它们实现相同的目地;MIPS 与 PowerPC 处理器相似,除了第 一个指令称为“加载链接”。) CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该 位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前 值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。” 通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新 值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。 类似于 CAS 的指令允许算法执行读-修改-写操作,而无需害怕其他线程同时 修改变量,因为如果其他线程修改变量,那么 CAS 会检测它(并失败),算法 可以对该操作重新计算。清单 3 说明了 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |