Java 线程安全与性能

Java 线程安全与性能,java,multithreading,synchronization,Java,Multithreading,Synchronization,我正在决定在实现所需点的线程安全性(同步)的同时,实现高性能增益的最佳方法是什么。 考虑下面的情况。系统中有两个入口点,我想确保没有两个或更多线程同时更新cashcounts和itemStore。因此,我创建了一个对象调用Lock,并按如下方式使用它 public class ForwardPath { public void fdWay(){ synchronized (Lock.class){ //here I am updating both cashAccount

我正在决定在实现所需点的线程安全性(同步)的同时,实现高性能增益的最佳方法是什么。 考虑下面的情况。系统中有两个入口点,我想确保没有两个或更多线程同时更新
cashcounts
itemStore
。因此,我创建了一个对象调用
Lock
,并按如下方式使用它

public class ForwardPath {
public void fdWay(){
    synchronized (Lock.class){
        //here I am updating both cashAccount object and
        //itemStore object 
    }              
  }
}

但是,如果频繁触发
ForwardPath
BackWardPath
,这种实现将大大降低性能

但在这种情况下,仅锁定
cashcount
itemStore
是很困难的,因为这两个对象在两个路径中都会多次得到更新


在这种情况下,有没有一种既能提高性能又能保证线程安全的好方法

这个示例太抽象了,您描述的内容太少,无法在方法中替代同步

为了获得高可伸缩性(请注意,这不一定在所有情况下都是最高性能),工作通常被细分为彼此完全独立的工作单元(这些工作单元可以在不进行任何同步的情况下进行处理)

让我们假设一个简单的例子,总结数字(纯粹是为了演示原理):

最简单的解决方案是使用一个累加器进行求和,然后将数字累加到累加器中。显然,如果您想使用多个线程,则需要同步累加器,使其成为主要争用点)

为了消除争用,您可以将数字划分为多个片-独立的工作单元。每个工作单元可以独立求和(例如,每个工作单元一个线程)。要得到最终的总和,将每个工作单元的部分总和相加。现在唯一需要同步的地方是组合部分结果时。例如,如果您有100亿个数字,并将它们划分为10个工作单元,那么您只需要同步10次,而不是在简单的解决方案中同步100亿次


这里的原则是一样的:确保您可以在不同步的情况下尽可能多地完成工作,然后组合部分结果以获得最终结果。考虑到单个操作级别,就是要细化粒度,以便能够很好地支持多线程。

通过使用线程来提高性能是一个体系结构问题,仅仅添加一些线程和同步不会起到作用,通常只会使代码出错,而不会比以前更快地工作。因此,您的代码示例不足以帮助您解决您似乎面临的实际问题,因为每个线程解决方案对于您的实际代码都是唯一的。

为什么要在
类上进行同步?此外,锁(即争用)越少,在不影响正确性的前提下,性能越好。首先,让代码正确。然后测量性能是否可以接受。如果您有性能问题,请查找其原因。如果原因是同步,那么,也只有这样,才能开始考虑不同的策略。否则做是过早的优化。大多数情况下,性能问题是由IO引起的,而不是由同步引起的。@SanjayT.Sharma您的建议是什么?因为我想基于单个对象锁定两条路径。否则,两条路径将由两个不同的线程工作。@JBNizet感谢您的支持thoughts@Ruchira您可以锁定普通对象,这是首选方式:
final object lock=new object()
public class BackWardPath {
public void bwdWay(){
   synchronized (Lock.class){
       //here I am updating both cashAccount object and
       //itemStore object
   }
  }  
}