在我的JavaEE应用程序中,我应该(确切地)在哪里使用同步

在我的JavaEE应用程序中,我应该(确切地)在哪里使用同步,java,multithreading,jakarta-ee,synchronized,volatile,Java,Multithreading,Jakarta Ee,Synchronized,Volatile,我正在使用JavaEE为游戏评论开发一个内容管理系统 我有一个非常简单的问题,就是: 我有一个带有游戏对象的ArrayList。每个游戏对象都有GameRank属性,这是一个简单的类,定义如下: public class GameRank { private int activity; private int positiveVotes; private int negativeVotes; public GameRank(int activity, in

我正在使用JavaEE为游戏评论开发一个内容管理系统

我有一个非常简单的问题,就是:

我有一个带有游戏对象的ArrayList。每个游戏对象都有GameRank属性,这是一个简单的类,定义如下:

public class GameRank 
{
    private int activity;
    private int positiveVotes;
    private int negativeVotes;


     public GameRank(int activity, int positiveVotes, int negativeVotes) 
     {
       this.activity = activity;
       this.positiveVotes = positiveVotes;
       this.negativeVotes = negativeVotes;   
     }
}
网站的访问者可以选择对游戏投赞成票或反对票,结果将使用ajax发送到服务器

因此,问题是:

我应该在哪里同步对GameRank对象属性的访问——它们的getter和setter方法,或者在处理用户投票的控制器Servlet中,并根据游戏id决定应该更新哪个对象

提前10倍


如果我决定在类内使用同步,我可以使用AtomicInteger作为建议的海报之一,或者:

public class GameRank 
{
private volatile int activity;
private volatile int positiveVotes;
private volatile int negativeVotes;


public GameRank(int activity, int positiveVotes, int negativeVotes) 
{
    this.activity = activity;
    this.positiveVotes = positiveVotes;
    this.negativeVotes = negativeVotes;

    this.checkAndFixValues();
}

private void checkAndFixValues()
{
    if(this.activity < 1) this.activity = 1;
    if(this.positiveVotes < 1) this.positiveVotes = 1;
    if(this.negativeVotes < 1) this.negativeVotes = 1;
}

public int getActivity() 
{
    synchronized(GameRank.class)
    {
        return activity;
    }
}

public int getPositiveVotes() 
{
    synchronized(GameRank.class)
    {
        return positiveVotes;
    }
}

public int getNegativeVotes() 
{
    synchronized(GameRank.class)
    {
        return negativeVotes;
    }
}

public void incrementActivitiy()
{
    synchronized(GameRank.class)
    {
        activity++;
    }
}

}
公共类GameRank
{
私人活动;
私家侦探;
私家侦探;
公共游戏排名(整数活动、整数正数、整数负数)
{
这个。活动=活动;
this.positiveVotes=positiveVotes;
this.negativeVotes=negativeVotes;
这是一个.checkAndFixValues();
}
私有void checkAndFixValues()
{
如果(this.activity<1)this.activity=1;
如果(this.positiveVotes<1)this.positiveVotes=1;
如果(this.negativeVotes<1)this.negativeVotes=1;
}
公共int getActivity()
{
已同步(GameRank.class)
{
返回活动;
}
}
public int getPositiveVotes()
{
已同步(GameRank.class)
{
返回阳性;
}
}
public int getNegativeVotes()
{
已同步(GameRank.class)
{
返回否定词;
}
}
公共无效增量活动()
{
已同步(GameRank.class)
{
活动++;
}
}
}

我说得对吗?

您可以在GameRank中引入一个同步方法,该方法将接受投票(+ve或ve),并相应地更新正反两个选项。

在Java EE中(或通常在使用servlet时),不同的请求由不同的线程处理。无论这些线程在何处操作共享对象,都需要某种同步


取决于您的持久化技术,情况可能是这样,也可能不是这样。对于JPA,通常为每个线程提供自己的持久性上下文,并在数据库中检测冲突更新。如果这样做,则不需要在JVM内进行同步,但如果由于更新冲突而无法提交事务,则可能需要实现重试逻辑。在使用JDBC时,如果您不跨线程共享JDBC对象(
Connection
Resultset
),情况也是如此。

将线程安全责任外部化的问题是,其他客户端可以随意忽略这些问题,从而破坏所有使用

最好将这些顾虑内化,并使您的类线程安全


幸运的是,JDK提供了一个为您完成所有工作的类:AtomicInteger。如果将计数器的类型更改为AtomicInteger,则可以简单地添加方法,以线程安全的方式递增它们。有关更多信息,请参阅AtomicInteger的javadoc。

我正在使用核心API进行数据库查询。因此,如果我有修改正面投票的synchronized increment()方法,并且我的getter方法也是同步的,这意味着方法increment()和getPositiveActivity()都是同步的不同线程不会同时调用?是。我想你不需要同步getter。如果你需要,你可以有。重要的是在值写入中保持一致性。-1:这是错误的,必须同步对共享状态的所有访问,以确保更新的可见性。