我在某个字段上有一个带有getter getInt()和setter setInt()的类,比如说字段。
Integer Int; 类的对象,比如SomeClass。
这里的setInt()是同步的-- getInt()不是。
我正在多个线程中更新Int的值。每个线程都得到值Int,并适当地设置它。线程没有以任何方式共享任何其他资源。
每个线程中执行的代码如下所示。
public void update(SomeClass c) {
while (<condition-1>) // the conditions here and the calculation of
// k below dont have anything to do
// with the members of c
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
// System.out.println("in "+this.toString());
}
}
} run()方法只是通过传递给它的params在构造函数内部更新的成员上调用上面的方法:
public void run() { update(c); } 当我在大的序列上运行这个线程时,线程并没有太多地交织--我看到一个线程在执行很长时间,而没有在中间运行任何其他线程。
一定有更好的方法来做这件事。
我不能更改SomeClass或调用线程的类的内部结构。
如何才能做得更好?
蒂娅。
//=。
编辑:
我不是在操纵线程的执行顺序。他们都有同样的优先权。只是我在结果中看到的是,线程没有平均地分配执行时间--其中之一,一旦接管,执行。但是,我不明白为什么这段代码会这样做。
发布于 2014-06-18 07:19:08
只是我在结果中看到的是线程没有平均分配执行时间
如果你追求效率,这正是你不想要的。从执行中拉出一个线程,并调度另一个线程通常是非常昂贵的。因此,做one of them, once takes over, executing on实际上是有利的。当然,当这是过度时,您可以看到更高的吞吐量,但更长的响应时间。理论上是这样。在实践中,JVM线程调度几乎可以用于所有目的,并且您不希望尝试在几乎所有情况下更改它。根据经验,如果您对毫秒级的响应时间感兴趣,那么您可能希望远离干扰它。
博士:这不是低效的,你可能想保持原样。
编辑:
尽管如此,使用AtomicInteger可能有助于性能,在我看来,比使用锁(synchronized关键字)更容易出错。但是,为了获得可测量的好处,您需要非常努力地打击该变量。
发布于 2014-06-18 07:11:28
JDK为多线程int access (AtomicInteger)提供了一个很好的解决方案:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
发布于 2014-06-18 09:00:45
作为Enno Shioji has pointed out,让一个线程继续执行可能是在某些情况下执行代码的最有效方法。
这取决于线程同步对代码的其他工作(我们不知道)造成了多少成本。如果您有一个循环,如:
while (<condition-1>)
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
}
}与同步成本相比,条件-1和条件-2的测试和k的计算相当便宜,Hotspot优化器可能会决定通过将代码转换为如下所示来减少开销:
synchronized (c) {
while (<condition-1>)
if (<condition-2>) {
// calculate k here
c.setInt(c.getInt()+k);
}
}(或者一个更复杂的结构,通过执行循环展开和跨synchronized块进行多次迭代)。底线是,优化后的代码可能会阻塞其他线程更长的时间,但让拥有锁的线程完成得更快,从而导致整体执行速度更快。
这并不意味着单线程执行是处理问题的最快方法。这也并不意味着在这里使用AtomicInteger是解决问题的最佳选择。它会产生更高的CPU负载,可能还会带来很小的加速,但它不能解决您的真正错误:
完全没有必要在循环中以高频率更新c。毕竟,您的线程并不依赖于及时看到对c的更新。甚至看起来他们根本没有使用它。因此,正确的解决方法是将更新移出循环:
int kTotal=0;
while (<condition-1>)
if (<condition-2>) {
// calculate k here
kTotal += k;
}
synchronized (c) {
c.setInt(c.getInt()+kTotal);
}现在,所有线程都可以并行运行(假设这里没有发布的代码不包含线程间依赖项),并且synchronization成本降低到最小。您仍然可以将其更改为AtomicInteger,但这不再那么重要了。
https://stackoverflow.com/questions/24278938
复制相似问题