Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can one break this (non?) thread safe object?

I replied to a question earlier about thread safety which did not get a definite answer (I think).

So I have been trying to convince myself that the design is broken (visibility) by having thousands of threads read and write that object - but I have not been able to get anything unexpected. That is obviously not a proof that it is thread safe, probably merely a proof of my own limitations!

I understand the risk of reordering but I don't see how it could apply in that case, in the sense that the clone instance in the bar() method is local and the change on its fields is done before being released to the outside world with return, after which the instance is effectively immutable. So a thread looking at the returned object would see it with its bar field already set to the correct value...

So my question is: what kind of code Could you show a piece of code that uses IsItSafe and that could lead 2 threads to see different values of the bar field of a given instance of IsItSafe?

For reference and ease of reading I copy the code here:

public class IsItSafe implements Cloneable {

    private int foo;
    private int bar;

    public IsItSafe foo(int foo) {
        IsItSafe clone = clone();
        clone.foo = foo;
        return clone;
    }

    public IsItSafe bar(int bar) {
        IsItSafe clone = clone();
        clone.bar = bar;
        return clone;
    }

    public int getFoo() {
        return foo;
    }

    public int getBar() {
        return bar;
    }

    protected IsItSafe clone() {
        try {
            return (IsItSafe) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new Error(e);
        }
    }
}
like image 948
assylias Avatar asked Mar 09 '12 12:03

assylias


People also ask

How can you make an object thread-safe?

Using Atomic Variable Using an atomic variable is another way to achieve thread-safety in java. When variables are shared by multiple threads, the atomic variable ensures that threads don't crash into each other.

What is not thread-safe?

Non-thread-safe: It does not check the safety of the threads which makes it faster to run but at the same time, it becomes more unstable and crashes very frequently. It refers to a single thread only builds.

What is thread-safe How do you make your code thread-safe?

thread-safety or thread-safe code in Java refers to code which can safely be used or shared in concurrent or multi-threading environment and they will behave as expected. any code, class, or object which can behave differently from its contract on the concurrent environment is not thread-safe.

Which one is a thread-safe object?

1) Immutable objects are by default thread-safe because their state can not be modified once created. Since String is immutable in Java, it's inherently thread-safe. 2) Read-only or final variables in Java are also thread-safe in Java. 3) Locking is one way of achieving thread-safety in Java.


2 Answers

Visibility problems can occur when a value your program has written to a variable is cached in the cpu cache and not written to RAM immediately. For this reason if thread A running on cpu A is writting a value without correct synchronization and thread B reads this value from cpu B he might see a stale value in RAM and not the most recent value (present only in the cpu cache of processor A).

In the example given you are using none of the mechanisms Java provides to ensure safe publication. That is synchronization, volatile or final fields set in the constructor.

Therefore one could imagine that in your example the reference to the create clone object becomes availabe but the values written to clones fields remains in the cpu cache. In this case other threads would not be able to read the up to date values.

To give some reference. Look at this example

class FinalFieldExample {
  final int x;
  int y;
  static FinalFieldExample f;
  public FinalFieldExample() {
    x = 3;
    y = 4;
  }

  static void writer() {
    f = new FinalFieldExample();
  }

  static void reader() {
    if (f != null) {
      int i = f.x;
      int j = f.y;
    }
  }
}

The class above is an example of how final fields should be used. A thread executing reader is guaranteed to see the value 3 for f.x, because it is final. It is not guaranteed to see the value 4 for y, because it is not final.

The argument you are making would hold for this example as well, wouldn't it? The instance is created, fields set in the constructor etc. However it is not thread-safe, since the value written to y needs not become visible to other threads. (The cited example is from JSR 133 (Java Memory Model) FAQ: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering)

Update: You have asked for code that demonstrates the problem. I asked a similar (more open) question once: How to demonstrate java multithreading visibility problems? The interesting thing with the code sample given is, that it will behave differently with different minor versions of Java, on different operating systems and wether using the client or server jvm. In that regard I found the sample quite interesting. What is important to note is, that it might well be impossible to actually create sample code that leads to a visibility problem with your code today. However next year cpu generation might implement a different caching policy and suddenly the problem appears. If you follow the guidelines of the Java Language Specification your save.

like image 81
Joe23 Avatar answered Oct 01 '22 07:10

Joe23


Your code is irrelevant.

The problem is simply this: If bar is not volatile and if access is not synchronized, if one thread changes its value, another thread is not guaranteed to see the change.

like image 42
Bohemian Avatar answered Oct 01 '22 06:10

Bohemian