You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jcs-dev@jakarta.apache.org by Hanson Char <ha...@gmail.com> on 2005/01/25 06:49:31 UTC
FooBar 1.5 Concurrency
Imagine a system which has only 2 types of operations {foo, bar} on
different keys, and must obey the following rules:
1) Concurrent foo's are allowed on the same key;
2) Concurrent bar's are allowed on the same key;
3) If foo and bar are concurrent on the same key, then
a) if foo happens before bar, bar must wait for all foo's in
progress to complete before proceeding;
b) if bar happens before foo, foo must abort.
I have the following code to try to achieve/illustrate the above. Is
there any simpler/better/faster way to do it ? Any way to avoid the
synchronized block altogether ? Or any utility classes I may use to
reduce the complexity ?
Thanks in advance,
Hanson
public enum FooBarType {
FOO,
BAR;
}
public class FooBar {
ConcurrentMap<String, FooBarType[]> synMap =
new ConcurrentHashMap<String,FooBarType[]>();
public void foo(String key) {
FooBarType[] lock = {FooBarType.FOO};
FooBarType[] otherLock = null;
synchronized(lock) {
otherLock = synMap.putIfAbsent(key, lock);
if (otherLock == null) {
// no concurrent foo nor bar on the same key, so doFoo.
this.doFoo(key);
synMap.remove(key); // release lock.
return;
}
}
// Race condition:
// either a FOO or BAR is being done on the same key at the same time.
switch(otherLock[0]) {
case FOO:
System.out.println("Concurrent foo on the same key: proceed.");
this.doFoo(key);
return;
case BAR:
System.out.println("Concurrent bar on the same key: abort.");
return;
}
}
public void bar(String key) {
FooBarType[] lock = {FooBarType.BAR};
FooBarType[] otherLock = synMap.putIfAbsent(key, lock);
if (otherLock == null) {
// No concurrent foo nor bar, so doBar.
this.doBar(key);
synMap.remove(key); // release lock
return;
}
// Race condition:
// either a FOO or BAR is being done on the same key at the same time.
switch(otherLock[0]) {
case FOO:
do {
// Wait till all FOO's are finished.
synchronized(otherLock) {
otherLock = synMap.putIfAbsent(key, lock);
}
} while (otherLock != null && otherLock[0] == FooBarType.FOO);
if (otherLock == null) {
// no concurrent FOO nor BAR.
this.doBar(key);
synMap.remove(key); // release lock
return;
}
// Must be a concurrent BAR.
// drop thru.
case BAR:
// Concurrent BAR.
this.doBar(key);
return;
}
}
private void doFoo(String key) {
System.out.println("doFoo must be only invoked when there is
no concurrent doBar on the same key.");
}
private void doBar(String key) {
System.out.println("doBar must be only invoked after all
concurrent Foo's are finished on the same key.");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-dev-help@jakarta.apache.org