accessing a String across multiple threads - java

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.

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/

Convert double check locking from using synchronized to locks in JAVA

Consider the following code implementing double check locking using the synchronized keyword in JAVA 8:
private static void redoHeavyInitialisation() {
if (needToReinitialise()) {
synchronized (MyClass.class) {
if (needToReinitialise()) {
doHeavyInitialisation();
}
}
}
}
The reason double check locking is used is because the initialisation is heavy (hence lazy) AND it can happen more than once (hence singleton pattern can not be used, correct me if I am wrong).
Anyway, first, how do you convert the code above to use Lock from the JAVA concurrent package instead of using synchronized keyword?
Only after that AND optionally, feel free to comment on using Lock or synchronized keyword which one is better.
Remember, this question is not about Lock vs synchronized comparison. Answer attempts without answering the code conversion part will not be picked as accepted answer.
Transformation of synchronized blocks to the equivalent block using ReentrantLock is pretty rote.
First you create a lock with the same or similar scope and lifetime as the object you were locking on. Here you are locking on MyClass.class, hence a static lock, so you can map this to a static lock in MyClass, such as MyClass.initLock.
Then just replace each:
synchronized (object) {
with
lock.lock();
try {
and each associated closing brace with
} finally {
lock.unlock();
}
Putting it all together you have:
private final static ReentrantLock initLock = new ReentrantLock();
private static void redoHeavyInitialisation() {
if (needToReinitialise()) {
MyClass.initLock.lock();
try {
if (needToReinitialise()) {
doHeavyInitialisation();
}
} finally {
MyClass.initLock.unlock();
}
}
}
Performance-wise there is little daylight between the approaches. They essentially have the same semantics and usually use similar underlying mechanisms. In the past, there have been performance differences - sometimes optimizations have gone in that affect one or the other, so on some JVMs you can find a difference, but the whole point of double checked locking is to avoid taking the lock anyway, so just do what's simplest. You only get the lock for a very small transitory period while the needToReinitialise() method is running, so the locking cost won't have any ongoing impact.
Consider the following code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HeavyInitializer {
static final Logger logger = LoggerFactory.getLogger(HeavyInitializer.class);
static HeavyInitializer singleton;
public static synchronized HeavyInitializer getInstance() {
if (singleton==null) {
singleton = new HeavyInitializer();
}
return singleton;
}
boolean initialized;
private HeavyInitializer() {
initialized = false;
}
public synchronized void initialize() {
if (!initialized) {
heavyStuffDoneHere();
}
}
public synchronized void reInitilize() {
if (needToReinitialise()) {
heavyStuffDoneHere();
}
}
private void heavyStuffDoneHere() {
initialized = true;
}
private boolean needToReinitialise() {
if (!initialized)
return false;
boolean ret = false;
//Do your check here... and set ret
return ret;
}
}
From Oracle's doc:
... then making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Trying to use Lock would be trying to reimplement the synchronized block. Not necessary.
Singleton Double checks the lock and prevents singleton object to break using serialization.
package pattern.core.java;
import java.io.Serializable;
public class Singleton extends Object implements Serializable {
private static final long serialVersionUID = 1L;
private static Singleton sg;
private Singleton() {
}
public static Singleton getSingletonObj() {
if (sg == null) {
synchronized (sg) {
if (sg == null) {
sg = new Singleton();
}
}
}
return sg;
}
/*
* this method ensures that new object will not be created for singleton
* class using serialization and deserialization
*/
protected Object readResolve() {
return sg;
}
/*
* #Override protected Object clone() throws CloneNotSupportedException {
* throw new CloneNotSupportedException(); }
*/
#Override
protected Object clone() throws CloneNotSupportedException {
return sg;
}
}

Using AtomicBoolean instead of synchronized blocks

Say I have a class with 2 instance variables and the following methods (simplified for this question):
private final Object lock = new Object();
private boolean running;
public MyClass() {
synchronized(lock) {
running = false;
}
}
public void methodA() {
synchronized(lock) {
running = true;
}
}
public void methodB() {
synchronized(lock) {
if (!running) {
return;
}
}
}
I was looking at this code, and after reading about AtomicBoolean, I thought that one might fit here, especially after looking at the MyClass constructor and methodA. I wasn't too sure about methodB though.
Assuming these methods could get called by multiple threads, would the following be thread-safe?:
private AtomicBoolean running;
public MyClass() {
running = new AtomicBoolean(false);
}
public void methodA() {
running.set(true);
}
public void methodB() {
if (!running.get()) {
return;
}
}
Will running.get() be guaranteed to see an update via running.set(true) or running.set(false) from another thread?
In your example, a simple volatile boolean would be enough, since you only seem to be doing atomic operations. AtomicBoolean is useful if you need the methods such as compareAndSet.
So in answer to your question, yes, when using a volatile boolean or an AtomicBoolean, other threads will see the updates to the variable.
Generally speaking these code blocks are not equal for methodB, because reading volatile variable does not create synchronization order.
Imagine you have some other field int x = 42 in your class, that is updated in methodB:
public void methodB() {
if (!running.get()) {
return;
}
if (x < 50) x++; // just example
}
Then you have several threads that call methodB:
when using synchronized keyword, updates are safe and visible to all threads.
when using AtomicBoolean/volatile visibility is broken
If there is no such case with variable updates and the task is just to guarantee visibility between methodA - methodB sequence, then it's OK - AtomicBoolean is enough for that.
Yes. From the Javadoc of AtomicBoolean:
A {#code boolean} value that may be updated atomically.
This means that any update to AtomicBoolean is indivisible. So, I would consider such use of AtomicBoolean to be thread safe.
You should still consider making the declaration of AtomicBoolean final:
private final AtomicBoolean running;

Threadsafe bidirectional association in 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.

Categories