线程获取错误的成员变量值

时间:2014-05-10 07:24:58

标签: java multithreading synchronization

在我的项目中,我面临着线程的奇怪问题。

  

此问题仅在我运行多个线程时发生   一次(负载测试)。

在我的项目中有多个拦截器,它拦截应用程序中不同级别的请求/响应,并将请求/响应发送到WritetoFile类,该类使用log4j框架将详细信息写入平面文件。

以下是示例拦截器代码。有多个拦截器,每个都可以并行处理。

/*we have multiple Interceptor class which will pre-process the 
request/response and then send it to WritetoFile*/

    public class IntercerptorA {

        // some code ...
        public synchronized void sendRequestToWritetoFile(IRequest request,IResponse response){
        WritetoFile wtf = new WritetoFile(); //this class is responsible for writing request/response information into LOG file
        wtf.setRequest(request);
        wtf.setResponse(response);
        Thread thread=new Thread(wtf, "t1");//**assume wtf.getRequest is having "ABC"**
        thread.start();
        }
    }

现在假设还有2个Interceptor,并且在代码中只有单行差异。

//For interceptorB
    Thread thread=new Thread(wtf, "t2");//**assume wtf.getRequest is having "DEF"**

//For interceptorC
    Thread thread=new Thread(wtf, "t3");//**assume wtf.getRequest is having "XYZ"**

以下是WritetoFile类的代码 - :

public class WritetoFile implements Runnable{

    private volatile IRequest request;
    private volatile IResponse response;

    public synchronized IRequest getRequest() {
        return request;
    }
    public synchronized void setRequest(IRequest request) {
        this.request = request;
    }
    public synchronized IResponse getResponse() {
        return response;
    }
    public synchronized void setResponse(IResponse response) {
        this.response = response;
    }

    @Override
    public void run() {
        // I have added synchronized as I was trying to resolve the issue
        synchronized(WritetoFile.class){
            putItInFile(this.request,this.response);
        }

    }
    private synchronized void putItInFile (IRequest request,IResponse response){
        // This is the logger where I find discrepancies
        LOGGER.info("Current thread is : "+Thread.currentThread().getName()+" data is"+request);
        //some code and  method call
    }

}

话虽如此,现在当我运行单个请求时, LOGGER.info(“当前线程为:”+ Thread.currentThread()。getName()+“data is”+ request); line给出如下输出 - :

  

当前线程是t1数据是ABC

     

当前线程是t2数据是DEF

     

当前线程是t3数据是XYZ

这完全没问题。但是,一旦运行多个线程我得到一些错误的输出,如下所示 - :

  

当前线程是t1数据是DEF

     

当前线程是t2数据是DEF

     

当前线程是t3数据是XYZ

似乎在线程t1可以在方法putItInFile中使用“wtf”对象的值之前,线程t2已经使用interceptorB中的setter重置了wtf值。但我的想法是,当我为每个线程创建新的实例WritetoFile类时,线程t2操作如何更改线程t1缓存。请让我知道我哪里出错了以及我需要改变什么。

提前致谢:)

3 个答案:

答案 0 :(得分:0)

很可能DEF请求在两个不同级别被截获,导致请求被记录两次。

答案 1 :(得分:0)

在任何地方使用 synchronized 都不会使类线程安全。

在你的情况下,只要WritetoFile.setRequest(request1)返回,就会有一个窗口没有保持锁定,任何其他线程都可以自由调用它,然后才有机会使用它。

不是将请求分配给实例变量,最好将它们添加到其中一个java.util.concurrent队列类中,并在Thread.run()方法中从队列中使用它们。

看看java.util.concurrent javadoc,因为那里有大量的例子。

答案 2 :(得分:0)

您的问题是教科书并发问题。 您有多个线程同时运行,能够读/写变量。

为了确保这些值保持正确,您需要在修改变量的代码周围添加一个锁,以便任何时候只有一个线程可以修改这些变量。

1)代码需要等待,直到修改变量的方法变为可用。 2)当线程完成修改变量并即将退出代码块时,它需要通知其他等待线程完成它。

请阅读API并查看您的代码,牢记以上几点,您应该没有问题修复它。