I am interested in the community opinion about the following approach for the synchronization. Generally it is based on the idea to have a configurable way to apply locking on some logic parts.
Any comments and review is appreciated :) .
lock.properties
keeps configuration:
foo=true
bar=false
SynFactory.java
produces locks:
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class SyncFactory {
private static HashMap<String, Object> locks = null;
public static synchronized Object getLock(String key) {
init();
return locks.containsKey(key) ? locks.get(key) : new Object();
}
private static void init() {
if (locks == null) {
try {
locks = new HashMap<String, Object>();
Properties properties = new Properties();
properties.load(SyncFactory.class.getClassLoader().getResourceAsStream("lock.properties"));
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
// key=true => locking with ine object
// key=false => lock object should always be new
if (Boolean.parseBoolean(String.valueOf(entry.getValue()))) {
locks.put((String) entry.getKey(), new Object());
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Service.java
actual usage:
public class Service {
public void foo() {
synchronized (SyncFactory.getLock("foo")) {
// do some logic
}
}
public void bar() {
synchronized (SyncFactory.getLock("bar")) {
// do some logic
}
}
}
-
\$\begingroup\$ What do you think you are accomplishing with this? \$\endgroup\$user4619– user46192017年01月31日 20:20:21 +00:00Commented Jan 31, 2017 at 20:20
5 Answers 5
- Your large outer
if
insideinit()
makes me a sad panda, why don't you just put a conditionalreturn
right in the beginning of the method? Still I'm curious whether you can provide a use-case for this approach. - Why even lazy? Do you expect no
getLock()
calls in most cases when your app is ran?
-
\$\begingroup\$ 1. There are two kind of people who do return first and who write if. As for the real world example I can't provide one but who knows what could happen in future and might be it would be mainstream. 2. It is done with a lazy initialization just for that example in real life I would leave it for the IOC container \$\endgroup\$ykhrustalev– ykhrustalev2012年08月03日 18:06:10 +00:00Commented Aug 3, 2012 at 18:06
Do you use synchronization to ensure visibility and prevent parallel running of two (or more) pieces of code? If yes, I agree with Dmitry Makarenko, I also don't see a real use-case of this class. The coder knows which pieces of code use the same shared data when they write the code, so runtime configuration is unnecessary.
If you use it only to prevent parallel running of two (or more) piece of code which do not access the same shared data it could be fine but SemaphoreFactory
would be a better, more intuitive name for this class.
Two other notes:
- Using
Properties.stringPropertyNames
andgetProperty
instead ofentrySet
would make theinit
method easier to read (no casting required) without a real performance loss (since it runs only once). Using a guard clause in the
init
method would make the code flatten:if (locks != null) { return; } try { ... } catch (IOException e) { throw new RuntimeException(e); }
I just don't see a point in this factory. It has nothing in common with locking except class name, getLock
method and "lock.properties" string inside. It's just a global hash map.
You always can (should) use synchronized
with this
or even better with private ivar. Any need too use your factory makes me think there is a bad design.
-
\$\begingroup\$ the point is to have configurable way to apply lock on the same object and have actually sync or crate new object each time and have no sync \$\endgroup\$ykhrustalev– ykhrustalev2012年08月03日 13:50:11 +00:00Commented Aug 3, 2012 at 13:50
Java 5 Semaphore is ready made, tested, and secure tool for your problem.
You certainly find something on the Net searching "semaphore java lock
"
-
\$\begingroup\$ Sorry I don't get how it could help. Your approach uses acquiring lock to control the state of sync, but it still requires some logic to apply the restrictions when to acquire or release the locking state on particular method. \$\endgroup\$ykhrustalev– ykhrustalev2012年08月03日 13:55:29 +00:00Commented Aug 3, 2012 at 13:55
-
\$\begingroup\$ No matter, I was not certain to be right for the way you are looking for, just tried to be helpful if can take advantage on resctriction and constrains pointed by Semaphore. However it seems you can use synchronized docs.oracle.com/javase/1.4.2/docs/api/java/util/Hashtable.html \$\endgroup\$cl-r– cl-r2012年08月03日 14:20:33 +00:00Commented Aug 3, 2012 at 14:20
Everyone else has failed to mention:
Locks on non-final
references are less than useless as they do not guarantee anything.
Right now, in both cases, you just have all the overhead of synchronized
with none of the guarantees! But worse, naive maintainers will think there is a guarantee when there is none.
Thread Safe and non-Thread Safe versions of classes exist for a reason. Whatever you think you are accomplishing with this, especially if it is performance related, you are misguided.
-
\$\begingroup\$ oh dear, it was sarcasm back in 2012, this code makes no sense, it was for fun only, but still thanks for paying attention to that \$\endgroup\$ykhrustalev– ykhrustalev2017年01月31日 20:36:34 +00:00Commented Jan 31, 2017 at 20:36
Explore related questions
See similar questions with these tags.