I have a requirement where I had to synchronize on string values but from reading many posts I concluded that synchronization must be done on a object that represented the string. So I have done same created a object for every string and stored this object in a concurrenthashmap. I use this hashmap's putIfabsent functionality to get the object from key string.After obtaining the object I synchronized on the object to perform string related operations.
But over a period the map started accumulating with number of objects. So I had to decide to remove object from the map if no thread is using the object.To implement this I added a counter to the object and used it to count thread . During decrementing I check if count is zero I delete the object from map.To work on the map I had to put putifabsent and increment operations in synchronized block with lock on the map itself. Similarly decrement and removal of object were synchronized on map. This is causing a performance overhead. I have to lock the map even if I have different string key's with different object look-up.
Is there any way that the design could be changed or improved so that rather than synchronizing on the map I just synchronize on the Object?
I had problem X so I decided to do Y, and now I have a problem with Y. Can you help me with that?
Frequently when somebody does that, it turns out that Y wasn't the right solution for X in the first place. So can we go back to problem X? In your case, it was that you decided that you had to do something and synchronize the processing on string values. Why was that? It can't be because you're changing the value of the string, because String objects are immutable, or can it?
Joined: Dec 11, 2010
Strings could be used in multiple places in the code and a lock on the String will cause unnecessary deadlock which leads to undebuggable code issues.
I am ready to change the design this was just a approach that I tried which works but with a bottleneck of performance problems. So I just posted with title X and solution Y which tried to achieve X might be a solution Z would help
Have you considered locking the actual file via java.nio.FileChannel.lock()
Joined: Dec 11, 2010
I researched a bit on filechannel lock but found that it worked in windows but faced issues in linux blocking lock on file is platform dependent. Also some suggestions are that I should use WeakHashMap and weak reference so that I dont need the overhead to maintain counters. Will it be really efficient to use weakhashmap? What would be the approach to use weakhashmap in such scenario I never used weakhashmap before so any help in this context is really appreciable.
From the API for java.nio.channels.FileChannel and its lock() method:
File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine.
In other words, file locks are intended to guard against other processes, not other threads within the same process (the same JVM). Synchronization, on the other hand, guards against other threads in the same process, but not against other processes. Depending on which you need to guard against, you may need one, or the other - or even both together. But they do different things.
amol skulkarni wrote:Consider a fact that I need to write a file based on the String lock.String is the path to the file.A lock on the string would indicate that no other thread is working on the file.
Ah. Well that's entirely different from what you described initially. Simply put, there is no simple way to isolate your changes to a file (which is why, I presume, you want to lock it) without some very sophisticated checking.
My opinion: Use a database instead of a file, because this sort of thing is exactly what they were designed for. And if you can break down the contents of your file(s) into logical tables, you'll probably be even better off.
Files are very crude, and it sounds like what you want to do is not. However, without more detail on what you're trying to do, it's difficult to offer advice.
Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Joined: Dec 11, 2010
Sorry this is like a reply after years but this was an interesting topic ....We used weak references to solve this issue. Object Pool when passed a String would return a weak reference. Over a period if there are no references to this object JVM cleans them up and the overhead of accumulation is automatically eliminated. Thanks all for your help it was a good discussion.
amol skulkarni wrote:Sorry this is like a reply after years but this was an interesting topic ....We used weak references to solve this issue. Object Pool when passed a String would return a weak reference. Over a period if there are no references to this object JVM cleans them up and the overhead of accumulation is automatically eliminated.
Still sounds to me like an overthought solution. Did you try using a database? Or is there something that prevents you from using one? Unfortunately, we (or at least, I) still don't have enough information about your original problem X to make a judgement.
But thanks for the update and, as Jesper said: Welcome back.