Threadsafe bidirectional association in Java - java

What is a good way to implement thread-safe bidirectional associations? Is there maybe a good library or code generator?
Here is a non thread-safe example:
class Foo {
private Foo other;
public Foo getOther() {
return other;
}
public void setOther(Foo other) {
this.setOtherSecretly(other);
other.setotherSecretly(this);
}
void setOtherSecretly(Foo other) {
if (this.other != null) this.other.other = null;
this.other = other;
}
}
My requirements for thread-safety are:
No deadlocks
Eventual consistency (When all threads stop modifying the objects, a consistent state is eventually reached. I.e., it is acceptable that assert foo.getOther().getOther() == foo fails when another thread is performing setOther concurrently.
Sequential behaviour. If a thread performs setOther and no other other thread overrides the value, getOther immediately returns the new value for that thread.
No traveling back in time. Once a thread observed a new value with getOther, it will never again receive the old value (unless it is set again).
Also nice to have:
Low contention, especially no global lock. The solution should scale well.
As little synchronization overhead as possible. It should have reasonable performance for a single thread.
Low memory overhead. When an object has 5 associations, I don't want 3 additional fields per association. Local variables in setters are ok.
My application will have 16 threads working on about 5.000 objects of several classes.
I couldn't come up with a solution yet (no, this is not homework), so any input (ideas, articles, code) is welcome.

Google Guava does this for you: BiMap.
For example:
BiMap<Integer, String> bimap = Synchronized.biMap(HashBiMap.create(), someMutexObject);
bimap.put(1, "one");
bimap.put(2, "two");
bimap.get(1); // returns "one"
bimap.inverse().get("one") // returns 1
someMutexObject can be any object you would want to synchronize on.

You can associate each object to their own lock and then set the other while acquiring both locks. For instance. To avoid deadlock you can use lock ordering
class Foo extends ReentrantLock {
private static final AtomicInteger order = new AtomicInteger(0);
final int id = order.incrementAndGet();
private Foo other;
public Foo getOther() {
return other;
}
public void setOther(Foo other) {
if (id > other.id) {
other.lock();
try {
this.lock();
try {
// assign here
} finally {
this.unlock();
}
} finally {
other.unlock();
}
} else if (id < other.id) {
this.lock();
try {
other.lock();
try {
// assign here
} finally {
other.unlock();
}
} finally {
this.unlock();
}
}
}
}

Try this, will allow reading while no writing is done.
ReentrantReadWriteLock

The other alternative is to simply make the other reference(s) volatile. That will meet your requirement and your nice-to-haves.

I can think of an static member to work as a monitor. but maybe this is what you consider 'global' lock.
class Foo {
private static final Object MONITOR = new Object();
private Foo other;
public Foo getOther() {
synchronized(MONITOR){
return other;
}
}
public void setOther(Foo other) {
synchronized(MONITOR){
this.setOtherSecretly(other);
other.setotherSecretly(this);
}
}
void setOtherSecretly(Foo other) {
if (this.other != null) this.other.other = null;
this.other = other;
}
}

This turns out to be a really hard problem! (Nice!) Using a global lock would be too easy, and probably too slow. I think I have a lock-free version--which I'll get into below--but I wouldn't put too much faith in it being perfect. It's hard to reason about all the possible interleavings.
As it turns out, this is a perfect use case for transactional memory! Just mark the whole block as atomic and modify whatever you want! You might look at Deuce STM, though I don't know how fast it might be. If only the best systems didn't need custom hardware...
Anyway, after thinking through this problem for a while, I think I came up with a version that bypasses locks using Java's AtomicReference. First, the code:
class Foo {
private AtomicReference<Foo> oRef = new AtomicReference<Foo>;
private static final AtomicInteger order = new AtomicInteger(0);
private final int id = order.incrementAndGet();
private static bool break(Foo x, Foo y) {
if (x.id > y.id)
return break(y, x);
return x.oRef.compareAndSet(y, null) &&
y.oRef.compareAndSet(x, null);
}
public void setOther(Foo f) {
if (f != null && f.id > id) {
f.setOther(this);
return;
}
do {
Foo other = oRef.get();
if (other == f)
break;
if (other != null && !break(this, other))
continue;
if (f == null)
break;
Foo fother = f.oRef.get();
if (fother != null && !break(f, fother))
continue;
if (!f.oRef.compareAndSet(null, this))
continue;
if (!oRef.compareAndSet(null, f)) {
f.oRef.set(null);
continue;
}
} while (false);
}
}
Key points:
If there are no concurrent accesses to any of the affected Foos (at most 4), the setter makes one pass through the loop modifying the relevant pointers.
In the presence of concurrent setters, some of the setters might fail and retry.
If multiple threads try to break a relationship concurrently, only one thread will succeed executing x.oRef.compareAndSet(y, null).
If f.oRef.compareAndSet(null, f) succeeds, no other thread will be able to break the half-established relationship in break(). Then if oRef.compareAndSet(null, f) succeeds, the operation is complete. If it fails, f.oRef can be reset and everyone retries.

Related

How to synchronize code based on boolean value?

I have this code:
private volatile boolean immortal;
private Object lock = new Object();
public void set(boolean immortal) {
this.immortal = immortal;
}
public void kill() {
// .... contains some other code.
synchronized(lock) {
if (!immortal) {
for (int i = 0; i < numThreads; i++) {
runnableList.add(POISON_PILL);
}
}
}
}
My use case is that I would like the if statement in the kill method to run to completion before immortal value is changed. Is there a better way of doing this without locking on an object?
I mean what is the best way to synchronize a block only if the value of a boolean variable is false and not allow the boolean value to be changed till it runs to completion? Can I achieve this using AtomicBoolean?
A neat way to do this could be to declare your runnableList as a synchronized list:
// where T is whatever type it needs to be
List<T> runnableList = Collections.synchronizedList(new ArrayList<>());
Then you could add to it without explicit synchronization:
if (!immortal) {
runnableList.addAll(Collections.nCopies(numThreads, POISON_PILL));
}
This works because a single call to addAll is atomic.
This isn't doing it without synchronization, though, it's just internal to the list.
With this said, it's hard to recommend a "better" solution because it's not clear what the requirements are. Synchronization (etc) is used to preserve the invariants of your object when operated on by multiple threads.
For example, why do you need immortal to remain unchanged while you add things to runnableList? How else do you access immortal and runnableList? etc
Use two locks:
private boolean immortal;
private final Object killMonitor = new Object();
private final Object flagMonitor = new Object();
public void set(boolean immortal) {
synchronized (flagMonitor) {
this.immortal = immortal;
}
}
public void kill() {
// ...
synchronized (flagMonitor) {
if (!immortal) {
synchronized (killMonitor) {
runnableList.addAll(Collections.nCopies(numThreads, POISON_PILL));
}
}
}
}

Synchronized method or Synchronized block : Which one is better while writing singleton class in java? [duplicate]

This question already has answers here:
What is an efficient way to implement a singleton pattern in Java? [closed]
(29 answers)
Closed 5 years ago.
As we know for synchronous operation while creating singleton class we make whole method as synchronized or only block of statements which are responsible for creation of object as synchronized.But, among these two approaches which one is better and why?
Approach 1
public static A getA(){
if (obj == null){
synchronized(Singleton.class) {
if (obj == null) {
obj = new Singleton();//instance will be created at request time
}
}
}
return obj;
}
Approach 2
public synchronized static A getA(){
if (obj == null){
obj = new Singleton();//instance will be created at request time
}
return obj;
}
Concept:
public synchronized static A getA(){
if (obj == null){
obj = new Singleton();//instance will be created at request time
}
return obj;
}
Using the synchronization keyword on a method (like in the example above) synchronizes access to that entire method, which is generally pretty safe but unless you have a very small method you may be synchronizing a bigger chunk of code than you absolutely need to, which is more of a performance hit than necessary. Because synchronized blocks/methods can only be accessed by one thread at a time, they really slow down processing. The larger a chunk of code you synchronize, the worse the performance hit is.
If you require only a single resource that is lazy loaded, you need to do something like this:
class MyClass {
private static volatile Resource resource;
private static final Object LOCK = new Object();
public static Resource getInstance() {
if(resource == null) {
synchronized(LOCK) { // Add a synch block
if(resource == null) { // verify some other synch block didn't
// write a resource yet...
resource = new Resource();
}
}
}
return resource;
}
}
One important thing here is the volatile modifier providing visibility for the whole threads in your app.
The first one is better because you don't acquire the lock when obj is not null, while the second approach acquires the lock each time.
I would take the first one, which has a double checked locking.
Maybe you can also try something like this:
public class MySingleton {
private static instance = new MySingleton ();
private MySingleton (){ }
public MySingleton getInstance {
return instance;
}
}
You'd better use Holder idiom
public class HolderFactory {
public static Singleton get() {
return Holder.instance;
}
private static class Holder {
public static final Singleton instance = new Singleton();
}
}
It is lazy because instance will be created upon first call to get() and it is thread-safe because class is guaranteed to be loaded by classloader in a single thread.
You could also check this link for more details regarding singletons and thread-safety: https://shipilev.net/blog/2014/safe-public-construction/

Is this a synchronized deadlock situation in android java?

Is instantiating an instance of SynchroClass as defined below and calling sCMethod going to cause a deadlock when the second sCMethod tries to get a lock on lockObject?
SO suggests I might mean something like Re-entrancy in Java saves us from a deadlock situation in this code sample.. How, why?, which seems to suggest that it is not a deadlock as the same object already has the lock ownership, but that talks about synchronized methods, so is at least a little different.
class SynchroClass {
static Object lockObject = new Object();
private boolean otherCondition = true;
public boolean sCMethod(boolean condition) {
synchronized(lockObject) {
if(condition) {
// some code
} else if(otherCondition) {
// some code
sCMethod(false);
// some code
} else {
// some code
}
return true;
}
}
}

accessing a String across multiple threads

I'm looking for some input here. I have a singleton class that contains a value which is updated every few seconds by a method within that class. Right now, access to this value across multiple threads is done via synchronization, which I would like to eliminate. Would this make sense?
class DataSegment {
private MetricsUpdater metrics = new MetricsUpdater.getInstance();
public String printValues() {
StringBuilder sb = new StringBuilder();
sb.append(value1);
sb.append(morevalues);
sb.append(metrics.myValue); // this is the value that's currently synchronized
return sb.toString();
}
}
class MetricsUpdater {
private String myValueSynchronized;
public String myValue;
public static MetricsUpdater getInstance() {
if (theInstance == null) {
theInstance = new MetricsUpdater();
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
private void updateMetrics() {
synchronized(myValue) {
// also, to keep things simple, I've replaced all of the actual logic with a method called someMethodToUpdateMyValue()
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
}
}
}
There can be many instances of DataSegment all reading from myValue, but the metrics class is a singleton. myValue only updates every 5 seconds or so and only MetricsUpdater is allowed to write to it. Does that make sense?
Does it even need to be synchronized at all if all of the other threads are only allowed to read it? I've run a boatload of JUnit tests on this, creating many instances of the DataSegment class all printing values like crazy and I have yet to see any concurrency issues.
There are some problems with your code.
1st Problem
synchronized(myValue) {
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
Thread.sleep(100);
}
your critical section is wrong because are taking lock on myValue. Suppose you put a Thread.sleep(100) before exiting critical section. Then it means other thread will take a lock on new myValue instance and thus can enter the critical section. if its a time thread and if its frequency is very high. Then you can have stale updated overriding the new ones.
Anyways its a bad Practice to acqurie lock on such monitors. Use ReentrantLock or synchronize on some final reference of String.
2nd Problem
public static MetricsUpdater getInstance() {
if (theInstance == null) {
theInstance = new MetricsUpdater();
}
return theInstance;
}
Your Singleton code is broken. Use DCL (Double Checked Locking see below in my solution sec).
Or Use private static MetricsUpdater theInstance = new MetricsUpdate();. Latter is better,
3rd Problem
sb.append(metrics.myValue);
The above code should be called in a synchronized context or declared as volatile. Latter is better
Solution 1 - Assuming someMethodToUpdateMyValue is thread safe
class MetricsUpdater {
private static volatile MetricsUpdater theInstance;
public volatile String myValue;
/**
* DCL . Please avoid
* Better use
* private static MetricsUpdater theInstance = new MetricsUpdate();
*/
public static MetricsUpdater getInstance() {
if (theInstance == null) {
synchronized(MetricsUpdate.class) {
if(theInstance == null) {
theInstance = new MetricsUpdater();
}
}
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
// if your someMethodToUpdateMyValue is thread safe
private void updateMetrics() {
myValue = someMethodToUpdateMyValue();
}
}
Solution 2 : Assuming someMethodToUpdateMyValue is not Thread Safe
No need of synchronization is reference read/write is atomic
and we have delared myValue as volatile
class MetricsUpdater {
private static volatile MetricsUpdater theInstance;
public volatile String myValue;
/**
** Use ReentrantLock instead
*/
private final Object lock = new Object();
/**
* DCL . Please avoid
* Better use
* private static MetricsUpdater theInstance = new MetricsUpdate();
*/
public static MetricsUpdater getInstance() {
if (theInstance == null) {
synchronized(MetricsUpdate.class) {
if(theInstance == null) {
theInstance = new MetricsUpdater();
}
}
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
private void updateMetrics() {
synchronized(lock) {
myValue = someMethodToUpdateMyValue();
}
}
}
It does need to be synchronized or the variables being read by multiple threads need to be marked as volatile (or anything else that causes java to flush the variable value). The java memory model does not guarantee that one thread will (ever) see the value of variable written by another thread. In practice, the values are often seen by multiple threads correctly, but if you want to ensure it, you must properly synchronize (or use volatile/locks/etc) to ensure the value is flushed.
Yes, the reading of myValue with have to occur in a synchronized block on the same lock to see the latest value of myValue.
So you could append myValue with:
synchronized (metrics)
{
sb.append(metrics.myValue); // this is the value that's currently synchronized
}
and change it with:
synchronized(this) {
// also, to keep things simple, I've replaced all of the actual logic with a method called someMethodToUpdateMyValue()
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
}
There's no need from what I see for myValueSynchronized either. You can use myValue as long as you keep myValue's value consistent as needed with the rest of the data in your object.

How to avoid Nested synchronization and the resulting deadlock

I need to lock two objects in a functionality and the current code looke like this;
Object obj1 = ...//get from somewhere
Object obj2 = ...//get from somewhere
synchronized(obj1){
...//blah
synchronized(obj2){
...//blah
}
}
As you can see this is a plain and straight recipe for deadlocks if another thread runs this piece of code with obj1 and two reversed.
Is there a way to avoid this situation using concurrency-utils locks?
I was contemplating maintaining a map of objects and their locks and verifying if they were available to take, but can't seem to come up with a clean way which will predict the lock order.
Although you preserve locking order, if obj1 is switched with obj2 you'll run into deadlock.
You must look for another solution to avoid this cases: lock ordering + optional tie breaking lock
int fromHash = System.identityHashCode(obj1);
int toHash = System.identityHashCode(obj2);
if (fromHash < toHash) {
synchronized (obj1) {
synchronized (obj2) {
........
}
}
} else if (fromHash > toHash) {
synchronized (obj2) {
synchronized (obj1) {
........
}
}
} else {
synchronized (TIE_LOCK) {
synchronized (fromAcct) {
synchronized (toAcct) {
...
}
}
}
Depending on what you are doing you may be able to take what you want from the first locked object and use that information to process the second locked object. e.g.
instead of
synchronized(list1) {
for(String s : list1) {
synchronized(list2) {
// do something with both lists.
}
}
}
do this
List<String> listCopy;
synchronized(list1) {
listCopy = new ArrayList<String>(list1);
}
synchornized(list2) {
// do something with liastCopy and list2
}
You can see you only have lock at a time so you won't get a deadlock.
You need to consistently lock in the order of obj1 and then obj2. If you never violate this order, you won't have deadlocks.
Essentially what you have is the dining philospher's problem.
https://en.wikipedia.org/wiki/Dining_philosophers_problem
Ovidiu Lupas's answer is similar to Dijkstra's Resource Heirarchy solution, but there are 3 more solutions, explained on the wiki page
This is what the arbitrator solution looks like. If all of the objects which you're operating from inherit from the same type, you could use static class variables to implement the arbitrators on the class of objects.
import java.util.concurrent.locks.Lock;
public void init()
{
Lock arbitrator = new Lock();
}
public void meth1()
{
arbitrator.lock();
synchronized (obj1) {
synchronized (obj2) {
arbitrator.unlock();
// Do Stuff
}
}
}
public void meth2()
{
arbitrator.lock();
synchronized (obj2) {
synchronized (obj1) {
arbitrator.unlock();
// Do Stuff
}
}
}
The Chandy/Misra solution requires a lot of message passing so I'm not going to implement it, but wikipedia has a pretty good explaination
You can solve it in other way I suppose.
class Obj implements Comparable<Obj> {
// basically your original class + compare(Obj other) implementation
}
class ObjLock implements Lock, Comparable<ObjLock> {
private final Lock lock;
private final Obj obj; // your original object
ObjLock(Obj obj) {
this.obj = obj;
this.lock = new ReentrantLock();
}
#Override
public int compare(ObjLock other) {
return this.obj.compare(other.obj); // ObjLock comparison based on Obj comparison
}
// + reimplement Lock methods with this.lock invocations
}
Then do
class ObjLocksGroup {
private final List<ObjLock> objLocks;
ObjLocksGroup(ObjLock... objLocks) {
this.objLocks = stream(objLocks)
.sorted() // due to ObjLock implements Comparable and sorting you are sure that order of ObjLock... will always be the same
.collect(toList));
}
void lock() {
this.objLocks.forEach(ObjLock::lock);
}
void unlock() {
this.objLocks.forEach(ObjLock::unlock);
}
}
And use it as you want:
ObjLocksGroup locks = new ObjLocksGroup(obj1, obj2) // the same as obj2, obj1, order does not matter anymore.
locks.lock();
locks.unlock();

Categories