0

For example I have the function as following:

public static final Function<A,B> MAP_A_TO_B(){
    return new Function<A,B>() {
        @Override
        public B apply(A) {
            switch (A) {
                case 1:
                    return B1;
                case 2:
                    return B2;
            }
            return B0;
        }
    };
}

But I don't know if it is thread safe or not, as my understand, since the method doesn't write to any class variable, it should be safe. Is my assumption correct ?

Thank you very much.

Xitrum
  • 7,765
  • 26
  • 90
  • 126
  • Which method are you referring to - `MAP_A_TO_B` or `apply`? – davmac Apr 05 '16 at 07:44
  • 5
    A method that only reads data can still not be threadsafe if it reads data that can be written by another thread. After all you'd have to analyze whether there could be at least one other thread that could alter the data a method is accessing directly or indirectly. In your case it would depend on what `B1` etc. are - if they could be replaced by another thread (e.g. someone could swap `B1` and `B2`) it would not be threadsafe. – Thomas Apr 05 '16 at 07:45
  • @davmac I'm referring to the MAP_A_TO_B method – Xitrum Apr 05 '16 at 07:46
  • @Thomas The only variable I concern is the A, which is served as a parameter. Since my knowledge about java threading is limited, I wonder will it a problem is Thread 1 is using MAP_A_TO_B, then thread 2 calls the same method, but with different A object – Xitrum Apr 05 '16 at 07:48
  • 1
    Since you are using `switch()` `A` would have to be an enum or some kind of immutable object (e.g. a string) and thus it should be threadsafe. If two threads call the same method simultaneously both calls will run in their own frames (which contain the parameters and local values) and thus are independent there. – Thomas Apr 05 '16 at 07:51
  • You should ideally use valid, compilable code in your example. – davmac Apr 05 '16 at 10:33
  • http://stackoverflow.com/questions/24128997/synchronized-in-java-proper-use/24143267#24143267 – Solomon Slow Apr 05 '16 at 15:26

3 Answers3

2

Rather than think of thread safety being a property of a method, think of it as a property of an item of data.

To be thread safe, an item of data must be immutable, or all changes to it must be automatically published to all threads (by being volatile), or all accesses (reads and writes) must be guarded by the same lock (synchronized object), or the object must be set up in a static initializer and never changed thereafter.

Java multi-threading & Safe Publication

Community
  • 1
  • 1
Raedwald
  • 46,613
  • 43
  • 151
  • 237
1

The MAP_A_TO_B method is perfectly threadsafe since it reads/modifies no state that is accessible to other threads.

Your code isn't actually compilable and the precise function of the apply method is a bit hazy:

   public B apply(A) {

The parameter must have a name.

                return B1;

If B is a type parameter, how can you be sure that B1 is of the correct type?

If you were able to resolve these issues, the thread-safety of the apply method comes down to the Bx expressions. Do these access or modify state (variables) that is accessible to other threads?

davmac
  • 20,150
  • 1
  • 40
  • 68
1

As davmac already stated, MAP_A_TO_B() is thread-safe because it always returns a new Function<A,B> object regardless of the state of the program. Likewise, this Function<A,B> object is thread-safe because it always performs the same logic: The only types which can be used in a switch statement are primitive wrapper types, String and Enum-- the first two are immutable and thus thread-safe and the last one is thread-safe because two different objects of the same Enum subtype cannot be equivalent (e.g. Fruit.APPLE and Fruit.PEAR will never be equivalent even if they have mutable states and happen to be in equivalent states --- such as if they had a non-final field name which was set to the same value).

However, instances of B must be assumed not to be thread-safe since we don't have any information about them in your example: Unless it is defined as otherwise, assume that code is not thread-safe. Furthermore, even if a type's current implementation is thread-safe, if the type itself is not defined as such, this implementation may change to be non-thread-safe in the future and break code which depends on it being thread-safe.

Lastly, to be a pedant, it's better to define a "last-resort" switch case using the default case:

public B apply(A) {
    switch (A) {
        case 1:
            return B1;
        case 2:
            return B2;
        default:
            return B0;
    }
}
errantlinguist
  • 3,658
  • 4
  • 18
  • 41