-1

This a much simplified version of my multithreading project and its just a way to replicate the issue in a simpler way for easy understanding.

So I have two classes startSession.java and main.java

what I am trying to do is to send a variable from startSession.java to main.java and Im also using multithreading. However, the problem I am facing is that everytime I try to retrieve the variable inside main I get a null value.

Inside startSession theres the run method and Setter(setSessionKey(String sess)) and getter(getSessionKey()) methods. I hardcoded a variable to test.

The get method only works inside the run method but when I call getSessionKey() from inside main I get a null as seen below. However, this is only a problem when I am using multithreading. When I dont use multithreading and instead just call the run method from inside main, the variable Im looking for is no longer null.

My question is there a way to send a variable from startSession to main while using multithreading ?

thank you

startSession.java

public class startSession extends Thread {

    static String sessionKey;

    public void run() {
        String createdSession = "83248329";
        setSessionKey(createdSession);
        System.out.println("Inside run method: " + getSessionKey());
    }

    public String getSessionKey() {
        return sessionKey;
    }

    public void setSessionKey(String sess) {
        sessionKey = sess;
    }
}

main.java

package com.Server;

public class Main {

    static String session;

    public static void main(String[] args) throws InterruptedException {
        startSession startSession = new startSession();

        startSession.start();

        session = startSession.getSessionKey();
        System.out.println("Inside Main: " + session);
    }
}

with multithreading

enter image description here

without multithreading

enter image description here

  • 2
    The problem is that your thread hasn't run yet, so it hasn't initialized the variable yet. The correct way to fix it- there could be a dozen different ones, depending on what you're actually trying to do. But in general, you can't start a thread then immediately depend on it having some value. You need to either use a callback to know when its been set, a reactive variable like in RxJava and subscribe to the value being changed, or use a signaling mechanism such as a mutex, semaphore, etc. – Gabe Sechan Jun 30 '22 at 05:18
  • @GabeSechan This is actually the same answer I gave with a code example but I was downvoted for it - twice. Also I would never modify variables inside a thread without the volatile modifier as this can lead to very funny issues. – Manuel Manhart Jun 30 '22 at 05:21
  • 1
    @ManuelManhart Your code example is wrong. It just reduces the likelihood of a race condition, it doesn't eliminate it. You did have the right root cause though. – Gabe Sechan Jun 30 '22 at 05:22
  • @GabeSechan In the provided / reduced example it does eliminate the possibility of a race condition. What is correct though that I should have marked that this should not be adapted to the real world implementation 1:1 - I did add some words of warnings now. But IMO this provides the questioneer with a new attempt for new solution finding. – Manuel Manhart Jun 30 '22 at 05:26
  • 1
    @ManuelManhart No it doesn't. Let's say the scheduler for the OS is really pinged and doesn't start your new thread for 2 minutes- which is perfectly legal. Your code would break. You aren't using any kind of synchronization, you're just assuming it will run in a certain time. Except on a hard real time OS, that isn't a valid assumption. In addition, 99.9% of the time you're sleeping for far longer than needed, being very inefficient in waiting. Use real synchronization and avoid both issues. – Gabe Sechan Jun 30 '22 at 05:48
  • @ManuelManhart BTW, an easy way to see your code fail- put a breakpoint on the first line of the run() function of the thread. Then run your code. After 500ms, you'll see the main thread finish sleeping and hit the code below, where it will print out null for the session key. This would be emulating what happens if the OS scheduler doesn't schedule your thread for 500 ms. – Gabe Sechan Jun 30 '22 at 06:03
  • @GabeSechan you are right with that the code is not a full solution. But my argumentation is that I indeed did not provide a full solution but hinted with the code on what is wrong / what to fix - As I don't think a full solution is possible as we do not know enough about the code. – Manuel Manhart Jun 30 '22 at 06:54
  • @ManuelManhart, Re, "I would never modify variables inside a thread without the volatile modifier." That seems like bad advice to give to a beginner. `volatile` is an advanced topic. Beginners should be taught first to use `synchronized` blocks for sharing variables. – Solomon Slow Jun 30 '22 at 13:21
  • @ManuelManhart, Re, "I don't think a full solution is possible as we do not know enough about the code." What more could you need to know? The question is about the code in the example. The example is complete. The example behaves differently from how the OP expected, and at least one answer here shows how to change it to _guarantee_ the expected behavior. The fact that OP originally encountered the same problem in some different, larger program is beside the point. – Solomon Slow Jun 30 '22 at 13:39
  • @CrimsonSpace, I added another downvote to sheng's solution. See my comment on that answer to learn why I did it. – Solomon Slow Jun 30 '22 at 14:42

1 Answers1

1

Use a BlockingQueue whereby the Thread (Producer) will add to the shared queue and the Main (Consumer) will block on the take

main

 public static void main(String[] args) throws Exception {

    // example only uses 1024 - check what is best for you
    BlockingQueue queue = new ArrayBlockingQueue(1024);

    StartSession producer = new StartSession(queue);

    ....
    System.out.println(queue.take());

startSession

   String createdSession= "83248329";
   queue.add(createdSession);

see https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

and https://jenkov.com/tutorials/java-util-concurrent/blockingqueue.html

Scary Wombat
  • 44,617
  • 6
  • 35
  • 64