阻止java线程共享数据?

时间:2011-08-09 08:59:17

标签: java thread-safety

我有一个应用程序(服务器端),它位于端口上并侦听客户端连接。 一旦建立连接,应用程序就会启动一个处理该连接的解析器(另一个线程)。

我的问题是,在某些时候(因为解析可能需要很长时间),服务器应用程序会在处理其他线程时启动新线程。这是一种理想的行为,本身并不是问题。发生的事情是新线程似乎从旧线程读取一些状态变量,因此行为错误。

松散地,解析器的作用是: 客户端总是发送两个数据包;第一个基本上是敲敲包,第二个是真正的数据包。 我读了第一个,如果我决定接受它,我把它放在一个变量中,以便可以读取下一个数据包。

在描述的场景中,第一个线程读取knock knock数据包并对其进行验证。 下一个数据包到达(在同一个线程上)并开始解析。

同时创建另一个解析器并等待其第一个数据包; 然后发生的问题(问题)是它检查验证变量(对于这个线程应该是假的)并且它发现它是正常的(它从前一个线程读取,它仍然在执行)并继续解析敲击敲打包好像是数据包。

什么是lokoing是一种完全消除数据共享的方法。我正在使用以下类来跟踪会话状态:

public class SessionInfo {

    private Constants.PacketValidity validity;
    private int packetSize;
    private String IMEI;
    private int packetReportedSize;
    private Constants.PacketType packetType;
    private int codec;
    private int records;
    private boolean valid;
    private Constants.ResponseType responseType;
    private String clientIP;
    private int serverPort;
    private Date parseInit;
    private Date parseEnd;
}

除此之外,该课程还有许多制定者和吸气剂。

解析器将此对象的实例作为私有字段。

我将如何实现这一目标?

2 个答案:

答案 0 :(得分:2)

您需要确保两个单独的线程使用两个单独的SessionInfo实例。

最简单的方法是创建一个新的解析器实例,然后创建一个新的SessionInfo实例。一旦你确定他们有单独的实例,你应该没事。

答案 1 :(得分:2)

  

解析器将此对象的实例作为私有字段。

这是你的问题。解决方案是创建一个新的SessionInfo并将其作为方法参数传递给解析器,并将其传递给进一步的方法调用。执行此操作后,对会话状态的引用将是当前线程执行的本地引用。

如果您的解析器包含更多在解析期间更新的私有属性,则还需要提取这些属性。将它们组合在一个私有子类中,并在调用解析时创建该类的实例将是解决该问题的可能方法。