11

I have a Java class that starts up 2 separate threads. The first thread starts up fine and all the variables are correct.

When I start the second thread the global variables from thread one changes to the values set in thread 2.

I have tried adding synchronized blocks where the global variables are updated, but this did not work.

Is there a way to solve this issue? I want each thread to start up and use its own values without interference in other thread values.

EDIT:

Snippet of my Thread class:

  public abstract class ConsumerIF implements Runnable {

      public static Element root = null;
      public static String name = null;
      public static String type = null;
      public static String location = null;

      public final synchronized void reconfigure() throws FatalDistributionException {


            Document doc = builder.build(new StringReader(xmlCollector));
            root = doc.getRootElement();
            Element nameElement = root.getChild("name");
            Element typeElement = root.getChild("type");
            Element locationElement = root.getChild("location");
            Element scheduleElement = root.getChild("schedule");

            if (nameElement != null && typeElement != null && locationElement != null){
                name = nameElement.getTextTrim();
                type = typeElement.getTextTrim();
                location = locationElement.getTextTrim();
            }

      }
  }
3
  • 2
    i. e. remove any static that you may have used Commented May 29, 2013 at 8:18
  • 1
    Pasting your code would be helpful Commented May 29, 2013 at 8:19
  • 1
    Static variables are shared between all instances of your 'ConsumerIF ' Commented May 29, 2013 at 8:28

5 Answers 5

19

Static variables are shared between all Threads, thats what makes them static. If you want to use different values, either use ThreadLocals or (much better), use different objects with non-static variables in the differrent threads. Without further code it's difficult to say more though.

Sign up to request clarification or add additional context in comments.

1 Comment

Simple yet defining. :)
6

Synchronisation merely controls the threads' access to the shared state.

If you want separate state per thread then you need to either declare different instances of that information (e.g. classes) per thread. e.g. simply instantiate a new object in each Thread's run() method, or perform a copy of the structure in question (e.g. a deep copy of a collection)

An alternative is to investigate ThreadLocal, in which each Thread will have a different copy of a nominated resource.

Comments

2

If you do not want your variable shared, then do not use a global variable (you probably mean static in Java). Create a new field with a new object initialized when your thread starts. Example:

public class HelloThread extends Thread {
    private MyObject myThreadVariable; // This is the thread-local variable

    public void run() {
        myThreadVariable = new MyObject(); // initialization when the thread starts
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new HelloThread()).start(); 
        (new HelloThread()).start();
    }
}

If you really need to access your objects locally to your thread across different pieces of code, then use ThreadLocal

public class UniqueThreadIdGenerator {
      private static final AtomicInteger uniqueId = new AtomicInteger(0);

      // Value obtained from uniqueNum.get() will be thread-local even though uniqueNum is static
      private static final ThreadLocal <Integer> uniqueNum = new ThreadLocal <Integer> () {
           @Override protected Integer initialValue() {
                return uniqueId.getAndIncrement();
           }
      };

      public static int getCurrentThreadId() {
           return uniqueNum.get();
      }
 }

What synchronization does is that it prevents two threads to enter the synchronized block of code at the same time. It's also related to sharing variables between threads but in the opposite case - when you want them shared. Without synchronization, your changes from one thread may or may not be visible to other threads (see here and here)

3 Comments

Thanks! I will remove the static variables? And have a look at ThreadLocal?
@lulu88 Looking at your code, just removing static should help.
Your first example should print "Hello from a thread with object: " + myThreadVariable to illustrate that each thread has a unique non shared instance of MyObject. Your second example has no need for ThreadLocal. AtomicInteger does all the work for you and will ensure unique Integer values.
1

If I understand correctly, you should probably look at the final modifier:

private final String s;

This ensures that s cannot be modified, thus your threads won't be able to change its value.

Also make sure that your threads do not attempt to modify values they shoudl not, copy them instead.

4 Comments

It's not mentioned that he does not want to modify at all, he just doesn't want another thread to modify.
I am still reading the post and I can't decide what he does and wants. "I want each thread to start up and use its own values without interference in other thread values." sound like final and/or copy for me. But it may just be that his variables are static and should not.
I am a girl :) lol but yes look at the snippet above - it does get modified, I just don't want other threads to modify my current thread values
Sorry, I was refering to he as OP (English isn't my native tongue), but in that case please discard my answer.
0

If you want to use static variables then you should use synchronized blocks on the class object inside your synchronized methods.

public abstract class ConsumerIF implements Runnable {

  public static Element root = null;
  public static String name = null;
  public static String type = null;
  public static String location = null;

  public final synchronized void reconfigure() throws FatalDistributionException {

     synchrnized(ConsumerIF.class) {
        Document doc = builder.build(new StringReader(xmlCollector));
        root = doc.getRootElement();
        Element nameElement = root.getChild("name");
        Element typeElement = root.getChild("type");
        Element locationElement = root.getChild("location");
        Element scheduleElement = root.getChild("schedule");

        if (nameElement != null && typeElement != null && locationElement != null){
            name = nameElement.getTextTrim();
            type = typeElement.getTextTrim();
            location = locationElement.getTextTrim();
        }
     }
  }

}

Make sure all your static variables are accessed from a synchronized method/block on the class object rather than on an instance variable or this instance. The synchronized method you have used is applicable on this instance means the current object with which you are calling the method and the static variables are shared by all the objects.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.