站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题关于多线程中为减少争用采用的锁崩溃方法

关于多线程中为减少争用采用的锁崩溃方法

摘要: 关于多线程中为减少争用采用的锁崩溃方法


取自IBM developerWorks 文章:轻松使用线程: 减少争用。

技术 3:锁崩溃

另一种能提高性能的技术称为“锁崩溃”(请参阅清单 6)。回想一下, Vector 类的方法几乎都是同步的。假设您有一个 String 值的 Vector ,并想搜索最长的 String 。进一步假设您已经知道只会在末端添加元素,而且元素不会被删除,那么,像 getLongest() 方法所展示的那样访问数据是安全的(通常),该方法只是调用 elementAt() 来检索每个元素,简单地对 Vector 的元素作循环。

getLongest2() 方法非常相似,除了在开始循环之前获取 Vector 上的锁之外。这样做的结果是当 elementAt() 试图获取锁时,JVM 将注意到当前线程已经拥有锁,而且将不会参与争用。 getLongest2() 加大了同步块,这似乎违背了“放进去,取出来”的原则,但因为避免了很大量可能的同步,调度开销的时间损失也少了,速度仍然快得多。

在运行 Sun 1.3 JDK 的双处理器 Linux 系统上,拥有两个线程,仅仅循环调用 getLongest2() 的的测试程序比调用 getLongest() 的要快 10 倍以上。虽然两个程序的序列化程度相同,但前者调度开销的时间损失要少得多。这又是一个极端的示例,但它表明争用的调度开销并不是微不足道的。即使只运行一个线程,崩溃版的速度也要快约 30% :获取您已占用的锁比获取无人占用的锁要快得多。


清单 6. 锁崩溃

Vector v;
...

public String getLongest() {
int maxLen = 0;
String longest = null;

for (int i=0; i String s = (String) v.elementAt(i);
if (s.length() > maxLen) {
maxLen = s.length();
longest = s;
}
}
return longest;
}

public String getLongest2() {
int maxLen = 0;
String longest = null;

synchronized (v) {
for (int i=0; i String s = (String) v.elementAt(i);
if (s.length() > maxLen) {
maxLen = s.length();
longest = s;
}
}
return longest;
}
}




这是一种奇妙的方法,推翻了一般认为的无同步方法快于无争用的同步方法,这是为何?


怎么样?


用wait notify


还是没人知道?


↑返回目录
前一篇: 编Java是否要JDK?
后一篇: 怎样编译包中的类?