views:

211

answers:

3

My program has a server thread and separate client threads that are individual connections to other servers. So how my program works is the client threads make individual requests, and when each of them so, I increment the shared variable iTimeStamp.

However, I need to access this shared variable value through my Server thread, but whenever I do try that it doesn't get the updated value, and the value of iTimeStamp that gets accessed is always zero.

I've just pasted the entire code below, I'd really appreciate if someone could tell me what I'm missing just so I can access the updated iTimeStamp value.

import java.util.Vector;
import java.lang.*;

public class Global {

public static int[] iParameter = new int[8];    

public static Global gb = null;

public static int iTimeStamp;

public static Global getInstance(){
    return gb;
}

Now, my main program that implements several classes that access the variables in the Global class as shared variables.

class ServerConnect extends Thread {

    Socket skt;
    int iProcessId, iInProcessId;
    int iOwnTimeStamp, iInTimeStamp;
    ServerConnect scnt = null;

    ObjectOutputStream myOutput;
    ObjectInputStream myInput;

    ServerConnect(){}
    ServerConnect(Socket connection, int iProcessNo) {
        this.skt = connection;
        this.iProcessId = iProcessNo;
    }

    public void run() {
        try {

            //initialize the object "scnt" using the parameterized constructor
            ServerConnect scnt = new ServerConnect(skt, iProcessId);
            myInput = new ObjectInputStream(skt.getInputStream());

            while(true) {
                try{

                    Object buf = myInput.readObject();

                    //if we got input, print it out and write a message back to the remote client...
//********************************************************************************
//part where im trying to access the shared variable    
                       //synchronized(Global.xlock){
                    iOwnTimeStamp = Global.getInstance().iTimeStamp;
                                        //}
//***********************************************************************************

                }catch(ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

class Server extends Thread {

    int iProcessId;
    int iPortNo;

    Server(){}
    Server(int iPName, int iPortNumber){
        this.iProcessId = iPName;
        this.iPortNo = iPortNumber;
    }

    public void run() {
        try{
            //first create a socket & bind it to port 9999
            ServerSocket myServerSocket = new ServerSocket(this.iPortNo);
            while(true) {
                //wait for an incoming connection
                Socket skt = myServerSocket.accept();
                ServerConnect sc = new ServerConnect(skt, iProcessId);
                Thread t = new Thread(sc);//Encapsulating each connection inot a class and running it as a separate Thread

                t.start();
            }
        }catch(IOException ex){
            ex.printStackTrace();
        }
    }
}


class Client extends Thread{
    int iProcessId; 
    String sMessage;
    Socket skt;
    //int iNumReq=0;

    ObjectOutputStream myOutput;
    ObjectInputStream myInput;

    //Constructor that accepts the processId, the corresponding socket and message if any
    Client(int iPid, Socket s, String m) {
        this.iProcessId = iPid;
        this.skt = s;
        this.sMessage = m;
    }

    public void run() {
        try {
            sleep((int)1*8000);
        }catch(Exception e) {}


        try {
            //Creating input and output streams to transfer messages to the server
            myOutput = new ObjectOutputStream(skt.getOutputStream());
            myInput = new ObjectInputStream(skt.getInputStream());

            //ive omitted the part where the client receives the reply from the server

    //sendMessage is called to send messages from the client to the server it is connected to
    void sendMessage(Object msg){
        if(msg!=null){
            try{
                myOutput.writeObject(msg);
                myOutput.flush();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

public class BaseStaInstance extends Thread {

    //variables for every BaseStation instance
    //int iTimeStamp=0;
    int iProcessId;
    Client[] clientList;
    private static BaseStaInstance bs = null;
    Utility u = new Utility();

        //I have the readFile() function implemented here which I have left out 

    //setProcessId()

    //setClientList()

       //getClientList()

    //getIpPort()

    //The connSetUp is used to set up the initial connection between clients and servers
    Client[] connSetUp(int iPid){
        //Broadcast to all processes other than itself
        ArrayList sPortList = u.getPortList(iPid);

        //making a consistency check to ensure the number of stations in the config file is equal to the number specified in the parameter file
        if(sPortList.size()!=(Global.iParameter[1]-1)){
            Global.iParameter[1]=sPortList.size()+1;
            System.out.println("Please note there was an inconsistency in the number of instances specified which was corrected as per the config file");
        }

        //creating the connections from this basestation to the other basestation instances on their ports
        Client[] clientList = new Client[Global.iParameter[1]-1];
        for(int i=0;i<Global.iParameter[1]-1;i++){
            String str = sPortList.get(i).toString();
            int iProcessToConnect = Integer.parseInt(str.substring(0,str.indexOf(",")));
            str = str.substring(str.indexOf(",")+1);
            String sMachineName = str.substring(0, str.indexOf(","));
            int iPortNo = Integer.parseInt(str.substring(str.indexOf(",")+1,str.length()));
            try {
                Socket skt = new Socket(sMachineName, iPortNo);         
                Client client = new Client(iProcessToConnect, skt, null);
                client.start();
                clientList[i] = client;
                try {
                    sleep((int)10000);
                }catch(Exception e){}
            }catch(Exception e){}
        }
        return clientList;
    }


    void broadcastReq(Object message){
        Client[] clientListValue = getClientList();
        for(int i=0;i<clientListValue.length;i++){
            Client client = clientListValue[i];
            client.sendMessage(message);
        }
    }

    void genRequest(){
        //while(true){
            try{
                sleep((int)(new Random().nextInt(50))*100); //The broadcast is done on a random basis
                //i has tried implementing the synchronized function but did not help
                //synchronized(Global.xlock){
                //increment the time stamp on generating the request
//********************************************************************************
//part where im incrementing the iTimeStamp variable.
                Global.getInstance().iTimeStamp++;
//********************************************************************************
                //}

                bs.broadcastReq("Request-BaseStation,"+iProcessId+","+Global.getInstance().iTimeStamp);

            }catch(Exception e){}
        //}
    }

    public static void main(String args[]){
        bs = new BaseStaInstance();

        //read the program parameters file
        bs.readFile();

        int iProcessId = Integer.parseInt(args[0]);
        bs.setProcessId(iProcessId);

        String sIpPort = bs.getIpPort();
        int iServ_port_no = Integer.parseInt(sIpPort.substring(sIpPort.indexOf(",")+1,sIpPort.length()));

        System.out.println("The port number: "+iServ_port_no);

        //Code to Debug---------
        //System.out.println("The Server Port No: "+iServ_port_no);
        //----------------------

        Server serv = new Server(iProcessId, iServ_port_no);
        serv.start();

        try {
            sleep((int)10000);
        }catch(Exception e){}

        Client[] clientList = bs.connSetUp(iProcessId);
        bs.setClientList(clientList);

        bs.genRequest();

    }
}

Its just the part that I've highlighted with ************ that I need help with figuring out, I've omitted some non related functions just to avoid crowding.

Thanks guys in advance

+2  A: 

Try making iTimeStamp volatile, or use java.util.concurrent.atomic.AtomicInteger

Jim Garrison
i managed to fix the bug.... i had used the volatile keyword, id used synchronized and everything i then declared the variable iTimeStamp as public static in my main class and accessed it using the class name in the other classes it still did not work i realized that the run() method in my ServerConnect class was accessing the value correctly, however the other function replyChoice which was being called from the ServerConnect class and which I left out from the code above couldn't get the updated value and the bug was fixed by just passing the value as a paramter to the replyChoice function
rookie
+2  A: 

Single variables shared by multiple threads should be declared with the volatile keyword. This ensures that any writes to that variable by one thread are immediately visible to all other threads. Without this, threads may have their own thread-local copy of the variable. You might also want to look into using one of the classes from the java.util.concurrent.atomic package, such as AtomicInteger.

Mike Daniels
i managed to fix the bug....i had used the volatile keyword, id used synchronized and everythingi then declared the variable iTimeStamp as public static in my main class and accessed it using the class name in the other classes it still did not worki realized that the run() method in my ServerConnect class was accessing the value correctly, however the other function replyChoice which was being called from the ServerConnect class and which I left out from the code above couldn't get the updated value and the bug was fixed by just passing the value as a paramter to the replyChoice function
rookie
+1  A: 

In global's constructor, you set gb = null. In getInstance() you return gb. There is no code posted that ever sets gb to any other value. This will result in null pointer exceptions.

Try changing the declaration inside global to

public static Global gb = new Global()
.

Also, you should consider setting it to private instaead of public - unless you want other threads to change the value of gb on you.

atk
i managed to fix the bug.... i had used the volatile keyword, id used synchronized and everything i then declared the variable iTimeStamp as public static in my main class and accessed it using the class name in the other classes it still did not work i realized that the run() method in my ServerConnect class was accessing the value correctly, however the other function replyChoice which was being called from the ServerConnect class and which I left out from the code above couldn't get the updated value and the bug was fixed by just passing the value as a paramter to the replyChoice function
rookie