2

In Java strings are special.

Since string literals with the same contents share storage in the common pool, Java's String is designed to be immutable. That is, once a String is constructed, its contents cannot be modified. Otherwise, the other String references sharing the same storage location will be affected by the change, which can be unpredictable and therefore is undesirable.

What if I synchronize on a String ? Will I lock across all instances of String sharing the same contents ?

For example : I have a multithreaded class which reads and writes from data files. There is 1 file per day and I want to synchronize read and writes to the same file so as to prevent unpredicatble behaviour. Can I simply synchronize on the filename (String) ?

3
  • 2
    string literals with the same contents share storage in the common pool. That means that "foo" == "foo". But that doesn't mean that any string with the same content as "foo" is == to "foo". Commented Apr 7, 2018 at 14:45
  • 1
    Locking on a string would be very error prone. There is zero encapsulation in that approach and it's impossible to enforce that policy for new code. Take advantage of OO principles and make a DailyFile class that actually enforces your locking policy As @Elevate suggested. Commented Apr 7, 2018 at 14:54
  • 1
    why do you think that you need to lock ? Other threads of your application may write/read the same file that which one used during the 1 day processing ? Commented Apr 7, 2018 at 14:58

2 Answers 2

7

You could intern the string, but it's a bit opaque to the next person who has to maintain the code. I'd suggest you create a File object or a separate Object called fileLock (say) to represent the intention more clearly.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, I agree but there are complexities with this solution also. A lock object would be required for each file and some sort of controller to index the lock objects. Whereas an interned String already provides this fonctionality with the advantage of garbage collecting Strings which haven't been used recently.
@klonq True, but then you don't need to worry about some other class coming along and trying to lock the same objects for an unrelated reason. Isolating there different components of your application is a good habit to get into.
Also someone else could easily break the application by synchronizing on the same string.
Personally, I'd prioritize making it clear what's going on for future developers (or you in six months' time!). By the way, interned strings are not garbage collected because the string pool has static references to them. So if your garbage profile is crucial to you, an interned string wouldn't be the way to go.
2

You can do it with String.intern():

String fileName = "fileName";
fileName = fileName.intern();
synchronized (fileName) {

}

6 Comments

@klonq If you are looking for some kind of file name based lock, this may help. stackoverflow.com/questions/5639870/…
I think that if another thread created before a "fileName" String (not literal) , it would have a different reference from the String returned by fileName.intern() and so the synchronized statement will not lock this other reference.
In this example you don't actually need to intern as string literal "fileName" is interned by default.
@davidxxx If that string which was created before was interned (like ("file" + "Name").intern()) then it will be the same instance.
@lexicode Sure I agree but it is not because the intern() is done at a place that we have the guarantee that that be the case everywhere. It was on the point on which I would stress on.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.