0

I have the following class:

public  class MyTestThreadStatic {

    private static int myNum;

        private MyTestThreadStatic () { // private constructor
        }
        public static void setMyNum(int val) {
            myNum = val;
        }
        public static int addOne() {
            return myNum + 1;
        }

.....

code block {
//thread 1 at t0
... some code to create a thread to call static class
System.out.println("val=" + MyTestThreadStatic.addOne());
... some other code to create a thread to call static class
//thread 2 at t0
MyTestThreadStatic.setMyNum(200);
System.out.println("val=" + MyTestThreadStatic.addOne());
}

        //stack created?

At t0 (time 0), two threads call function addOne. Will this work as expected? Will it work because two stacks were created? I would want to test this and looked at Thread and Runnable, but I am not seeing a way since neither have static methods and require object instance.

paulj
  • 327
  • 1
  • 9

2 Answers2

1

You don't need to test that; it is obvious that this is not thread safe. When there is shared information, and that information is read/written in parallel, you need some way of protection.

Which is not there in your code. Thus: as soon as you have multiple threads "working" that counter in ways that can lead to different results in different scenarios, all bets are off.

If your question is: how can I write a program that shows threading issues, you can do something like:

  1. Create a method that reads that int value, and then increases it by 1
  2. Create n threads; and each one simply calls that method m times

Now you would expect that the final value of the counter should be n x m. But you should find quickly that the counter will not have that exact value in the end!

If you want to "see" such effects with the two methods that you created, you would need something like this (pseudo code example)!

public void loopUntilMismatch() {
  while (true) {
    int value = random number
    setMyNum(value);
    int increasedValue = addOne();
    if (increasedValue != value + 1) {
      print "fail ...
      exit
    }
  }

When you run that method using multiple threads, it shouldn't take long until fail is printed and your program exits.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • BTW The `addOne()` is not `return myNum++;` which is what I think was intended. – Peter Lawrey Oct 20 '16 at 19:42
  • Yes. That is what I was looking for. – paulj Oct 21 '16 at 14:52
  • @paulj Glad to hear that. If so, consider accepting my answers - I guess you wont get any others any more. – GhostCat Oct 21 '16 at 14:54
  • Maybe this is clearly: http://stackoverflow.com/questions/3489543/how-to-call-a-method-with-a-separate-thread-in-java. I can not do this because class is static and when I attempt to implement Runnable, it will not compile. So how could I set up two threads to test a static class. – paulj Oct 21 '16 at 14:55
  • That would be kind of another on top question. But: your last comment simply shows that you should spent more time on learning **the basics** of Java first. You can very well write Runnables that work with static fields of some other class (actually that is *super easy*). So if **that** gives you trouble, then seriously: multi-threading is **way beyond** what you should currently deal with. You are like a person asking "please show me how to drive that formula 1 car with 150 mph on that curvy path ... and btw: how do I start the engine, and what is this cludge-thing about?!" – GhostCat Oct 21 '16 at 14:58
  • Dont get me wrong: I dont want to be rude. But i think you will **overburden** yourself when you try to go for multi-threading without understanding how to write down code that uses static stuff. – GhostCat Oct 21 '16 at 14:59
1

It's not thread safe, nor does it attempt to be.

A test cannot prove code is thread safe. It can only attempt to prove it's not thread safe.

To prove it's not thread safe you just need to rearrange the lines of code like this

System.out.println("val=" + MyTestThreadStatic.addOne()); // Thread 1

MyTestThreadStatic.setMyNum(200); // thread 2
System.out.println("val=" + MyTestThreadStatic.addOne()); // thread 2

As each thread can execute in any order you can run the code like this

MyTestThreadStatic.setMyNum(200); // thread 2
System.out.println("val=" + MyTestThreadStatic.addOne()); // Thread 1
System.out.println("val=" + MyTestThreadStatic.addOne()); // thread 2

Now both threads print the same thing.

The only way to prove code is thread safe is to understand it and determine there is no way you can get an error when multiple threads access it no matter what order the each thread is executed.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • @GhostCat yes, I was in the middle of change the line and got ti messed up. ;) – Peter Lawrey Oct 20 '16 at 19:40
  • 1
    One reason for this is that "thread safety" isn't a thing, it's the absence of a thing, or indeed several things (race conditions, deadlocks and so on). Not to mention that in the wider sense, thread safety depends on what you expect the code to do. So in that respect, sometimes even analysing the code on its own isn't enough. – biziclop Oct 20 '16 at 19:54
  • @biziclop agreed. StringBuffer is notionally thread safe, but almost impossible to use in a thread safe manner without additional locking. – Peter Lawrey Oct 20 '16 at 20:11