0

I have a service class that is an implementation of an interface and it's annotated with Spring as a service and a singleton. I have two different methods where each creates a string builder local variable. I have a private method that takes a string builder and a string, and both parameters are final variables. This private method appends information to that string builder depending on the information found in that additional string variable. In each implemented method I call that private method passing the locally created string builder and the necessary string.

I am confident that the two implemented methods are thread safe, but I am unsure about the private method. Is that string builder thread safe when I pass it like that? Does having the parameters as final help? I assumed the final made that thread safe, but at the same time I thought having it final means I couldn't append anything to it.

This stackoverflow question and answer says it wouldn't be, but in the example the parameter is not final, but maybe that does not matter.

Is that StringBuilder variable thread safe in this code?

Here's an example of what I have:

@Service
@Scope("singleton")
public class SingletonService {

    @Override
    public String buildSelect(final Integer id){
        StringBuilder sb = new StringBuilder("select * from table ");
        Map<String,Object> properties = new HashMap<String,Object>();
        addWhere(sb,properties,id);
        return sb.toString();
    }

    @Override
    public String buildCount(final Integer id){
        StringBuilder sb = new StringBuilder("select count(id) from table ");
        Map<String,Object> properties = new HashMap<String,Object>();
        addWhere(sb,properties,id);
        return sb.toString();
    }

    private void addWhere(final StringBuilder sb, final Map<String,Object> properties, final Integer id){
        if(id != null){
            sb.append("where id = :id);
            properties.put("id",id);
        } 
    }
}
Community
  • 1
  • 1
Elrond
  • 435
  • 1
  • 5
  • 14

2 Answers2

1

final has absolutely no effect when used in the method signature other than making it so you can't accidentally assign something to the variable inside the method.

Other than that ... why wouldn't this code be thread safe?

The only thing you're passing in to your public methods is an Integer which is immutable and nothing else external to the methods is ever modified.

So yes, since there's no concurrency involved, this is threadsafe.

That said, it also doesn't make a lot of sense. You're creating a Map, putting something in it, then discarding it.

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • Yes, that does look a little ridiculous looking at it. This is not the entire class, just a quick example and I didn't remove the map portion thoroughly enough. I was more worried about the string generation than anything else. Thanks for your answer. In regards to the final of the variable - I'm changing the value of the variable but indirectly through it's append method - final would come into play if I tried to assign a new string builder instance to it? – Elrond May 10 '13 at 22:03
  • @Elrond - correct. `final` in java means that you can not re-assign to a variable after the initial assignment; it doesn't have anything to do with object the variable is holding a reference to. You're not changing the *value* of the variable, you're using the object referred to by the variable. see: http://stackoverflow.com/a/10340003/302916 – Brian Roach May 10 '13 at 22:05
1

Yes, that is thread-safe.

Each thread gets its own stack where the variables are stored. In this case the variable is a reference, one for each thread, to the instance of StringBuilder created by that thread. The instances of StringBuilder will have been created in the heap and so could be shared but you would have to explicitly pass the reference between threads for that to happen.

Nick Holt
  • 33,455
  • 4
  • 52
  • 58