Java 使变量易失性是否消除了:多线程正确性-不一致的同步
我在下面的代码中发现声纳同步错误不一致Java 使变量易失性是否消除了:多线程正确性-不一致的同步,java,multithreading,sonarqube,Java,Multithreading,Sonarqube,我在下面的代码中发现声纳同步错误不一致 public int getMessageCount() { return m_messageCount; } public void onMessage(XQMessage msg) throws XQServiceException { synchronized(this) { m_messageCount--; // add the message to the result m_messages.add(msg);
public int getMessageCount()
{
return m_messageCount;
}
public void onMessage(XQMessage msg) throws XQServiceException
{
synchronized(this)
{
m_messageCount--;
// add the message to the result
m_messages.add(msg);
if (m_messageCount == 0)
{
// wake up client
finished();
}
}
}
“返回m_messageCount”时出错。如果我使m_message不稳定,它会解决问题吗?因为您在修改
m_messageCount
时使用了synchronized(this)
,所以可以使getMessageCount()
方法同步化,这将解决您的问题
例如:
public synchronized int getMessageCount(){
return m_messageCount;
}
由于您在修改m_messageCount
时使用的是synchronized(this)
,因此可以使getMessageCount()
方法synchronized
解决您的问题
例如:
public synchronized int getMessageCount(){
return m_messageCount;
}
@jameslarge你能在单独的帖子中给出这个原子整数的建议吗
我在想,像这样的事情:
static final int INITIAL_MESSAGE_COUNT = ...;
AtomicInteger messageCount = new AtomicInteger(INITIAL_MESSAGE_COUNT);
public int getMessageCount()
{
return messageCount.get();
}
public void onMessage(XQMessage msg) throws XQServiceException
{
int mc = messageCount.decrementAndGet();
messages.add(msg);
if (mc == 0) wake_up_client();
}
注意:messages.add()
调用位于实现中的synchronized
块中。在我的版本中不再是这样。我不知道什么是消息
,但是如果您依赖同步块来保护它,那么您必须将同步添加回。在这一点上,您最好使用原始版本:AtomicInteger比使用常规的int
更复杂。我不使用它,除非它允许我在不使用synchronized
块的情况下实现某些算法
附则。;调用onMessage()时,如果消息计数已经为零,应该发生什么?那会发生吗?如果发生这种情况,您将得到负面消息计数。我没有足够的信息知道这是好事还是坏事
p.p.S。;那XQServiceException
呢?无论messages.add()是否引发异常,我们的两个实现都将减少消息计数。那可能不是你想要的。我不知道
@jameslarge你能在单独的帖子中给出这个原子整数的建议吗
我在想,像这样的事情:
static final int INITIAL_MESSAGE_COUNT = ...;
AtomicInteger messageCount = new AtomicInteger(INITIAL_MESSAGE_COUNT);
public int getMessageCount()
{
return messageCount.get();
}
public void onMessage(XQMessage msg) throws XQServiceException
{
int mc = messageCount.decrementAndGet();
messages.add(msg);
if (mc == 0) wake_up_client();
}
注意:messages.add()
调用位于实现中的synchronized
块中。在我的版本中不再是这样。我不知道什么是消息
,但是如果您依赖同步块来保护它,那么您必须将同步添加回。在这一点上,您最好使用原始版本:AtomicInteger比使用常规的int
更复杂。我不使用它,除非它允许我在不使用synchronized
块的情况下实现某些算法
附则。;调用onMessage()时,如果消息计数已经为零,应该发生什么?那会发生吗?如果发生这种情况,您将得到负面消息计数。我没有足够的信息知道这是好事还是坏事
p.p.S。;那XQServiceException
呢?无论messages.add()是否引发异常,我们的两个实现都将减少消息计数。那可能不是你想要的。我不知道 如果我让m_messageCount变为volatile,它也会解决问题吗?如果你让它变为volatile
,你就不会再收到错误,但结果会不一致,因为m_messageCount
可以在onMessage(…)
方法中修改之前返回。@Ahmad.Masood我不知道Sonar会说什么,但如果我是您的代码审阅者,我会要求您保持一致。在代码访问的任何地方使用synchronized
,或者将其设置为AtomicInteger
,并在任何地方使用原子方法(例如。decrementAndGet()
)。@Titus,即使它在任何地方都是同步的,仍然存在竞争条件。如果一个线程调用getMessage()
,而另一个线程同时尝试调用onMessage()
,那么其中一个线程将赢得比赛,getMessage()返回的值将取决于哪个线程获胜。如果这是一个问题,那么只能通过在程序的更高级别上进行同步来解决。@MickMemonic我想你是对的,应该根据您正在尝试做的事情来选择这些事情,而OP的问题并不清楚。如果我将m_messageCount设置为volatile,它是否也会解决问题?如果将其设置为volatile
,您将不会再收到错误,但结果将不一致,因为m_messageCount
可以在返回之前返回在onMessage(…)
方法中修改。@Ahmad.Masood我不知道Sonar会说什么,但如果我是你的代码审阅者,我会要求你保持一致。在代码访问的任何地方使用synchronized
,或者将其设置为AtomicInteger
,并在任何地方使用原子方法(例如。decrementAndGet()
)。@Titus,即使它在任何地方都是同步的,仍然存在竞争条件。如果一个线程调用getMessage()
,而另一个线程同时尝试调用onMessage()
,那么其中一个线程将赢得比赛,getMessage()返回的值将取决于哪个线程获胜。如果这是一个问题,那么只能通过在程序的更高级别上进行同步来解决。@MickMnemonic我想你是对的,应该根据你正在尝试做的事情来选择这些事情,而OP的问题并不清楚。