简体   繁体   中英

Cannot share List value between threads using volatile

The server is initialized then thread started. The thread writes to List<String> JSON_LIST . When http request comes to parent thread it shows that JSON_LIST is empty however other thread have already added new element. Why volatile is not working?

import com.sun.net.httpserver.HttpServer;
import com.sun.jersey.api.container.httpserver.HttpServerFactory;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;

public class HelloWorld extends Thread {
            @GET
            @Produces("text/plain")
            public String getClichedMessage() {
                // Return some cliched textual content
                return JSON_LIST.get(JSON_LIST.size() - 1);
            }
            private volatile List<String> JSON_LIST = new ArrayList<String>();

            public void addJSONRecord(String s){
                 JSON_LIST.add(s);
            }
         @Override
            public void run() {
                 addJSONRecord(json);
        }

         public static void main(String[] args) throws IOException {
        HttpServer server = HttpServerFactory.create("http://localhost:8080/");
    server.start();
    (new HelloWorld()).start();

    System.out.println("Server running");
    System.out.println("Visit: http://localhost:8080/service");
    System.out.println("Hit return to stop...");
    System.in.read();
    System.out.println("Stopping server");
    server.stop(0);
    System.out.println("Server stopped");
        }

UPDATE

I have one class. It should acts as web server. Additional theread was created to populate JSON_LIST with records. The problem is when I try to return JSON_LIST.get(JSON_LIST.size() - 1) it always returns ArrayindexOutOfBound exception. Therefore, Jersey thread cannot see updates made to private volatile List<String> JSON_LIST .

How to fix it?

UPDATE2:

I have tried several things:

private volatile CopyOnWriteArrayList<String> JSON_LIST = new CopyOnWriteArrayList<String>();

and

public String getClichedMessage() {
            synchronized (JSON_LIST){
            return JSON_LIST.get(JSON_LIST.size() - 1);
            }

    }
    public void addJSONRecord(String s){
        synchronized (JSON_LIST){ 
            JSON_LIST.add(s);
        }
    }

Nothing solved the problem

Because volatile only guarantees the visibility of a new value of JSON_LIST. Ie, it guarantees that, if you assign a new list to the JSON_LIST variable in thread A, thread B will see the new value of the variable.

Changes to the list referenced by the variable are not made thread-safe by volatile. You need a thread-safe list to have such a guarantee, or you need to synchronize every access to the list.

EDIT:

reading your code again, this seems more than a concurrency problem. Jersey doesn't use the same HelloWorld instance than the one you explicitely create and start in your main method. So your main method adds in a list, and Jersey reads in another one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM