How to conditionally disable a synchronized block in Java? - java

Can I do something like that:
synchronized(isSynchronized ? myLock : null) {
}
I want to disable/enable synchronization through a flag. Is it possible?

You could use a lock (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html) and lock it manually.
if (shouldSync) {
lock.lock();
}
try {
// do your stuff
} finally {
if (shouldSync) {
lock.unlock();
}
}

The parameter passed into the synchronized block is not a statement but rather a object to synchronize upon (the mutex). To disable synchronization for whatever reason you should encase the statement in a if-condition as such:
if(condition){
synchronized(myLock){
// Critical segment
}
}
note however, if the evaluation of condition can be dependent on several threads (i.e. multiple writes to a boolean from different threads) you may need to use an existing thread-safe mechanism like AtomicBoolean as such:
AtomicBoolean condition = ... // defined elsewhere
if(condition.get()){
synchronized(myLock){
// Critical segment
}
}
if you need conditional synchronization upon a synchronized method, remove the synchronized keyword from the method declaration and move it into the body:
public synchronized void foo(){
// Critical segment
}
to
public void foo(){
if(condition){
synchronized(this){
// Critical segment
}
}
}

You can't synchronize of null. So if you have another mutex, then definately you could do something like:
synchronized(isSynchronized ? myLock : myLock2) {
}
else you could check and enter the critical section like:
if (isSynchronized) {
synchronized(myLock) {..}
}

Sure. Use an if before hand. Also, make sure the variable isSynchronized is marked volatile.
if (isSynchronized) {
synchronized(myLock) {
// ...
}
}
of course, that won't be synchronized when isSynchronized is false. And that doesn't sound like a great idea, if it's thread-safe it shouldn't be synchronized. If it isn't thread safe, it should be synchronized.

How about this for starters:
if (isSynchronized) {
synchronized(lock) { return doStuff(...); }
} else {
return doStuff(...);
}
private MyType doStuff(...) {
...
}

Related

how do I save or update an object in a thread safe way using JPA?

How can I make the code below thread safe?
objects.forEach(object -> {
Boolean objectExists = objectRepository.existsByObjectNameAndFormatAndLocale(
object.getObjectName(),
object.getFormat(),
object.getLocale());
if (!objectExists){
objectRepository.save(object);
}
});
please put below code inside synchronized block , to execute below current class object lock is required.
synchronized (this) {
//code
}
hope it will work for you
Your "forEach" needs to run atomic, so how about
private synchronized void saveIfNew(YourObjectClass obj) {
boolean objectExists = objectRepository.existsByObjectNameAndFormatAndLocale(
object.getObjectName(),
object.getFormat(),
object.getLocale());
if (!objectExists){
objectRepository.save(object);
}
}
objects.forEach(this::saveIfNew);
There are much better and more advanced at making things thread-safe, so some might object to making the entire "saveIfNew" method synchronized, but it's a good place to start.

Is it possible to synchronize a half of an if-block?

The question may seem pretty obvious, but it's not clear to me anyway.
I have the following class:
public class MyClass{
private Object lock = new Object();
private boolean flag;
public void method(){
//Start synchronization block
if(!flag){
flag = true;
//end synchronization block
//do some bulk operation, should be synchronized
}
//some other staff
}
}
The thing is I cannot put the piece of code I need to be synchronized, because it will not be correct. How to do such synchronization? Maybe there's something from java.util.concurrent that I could make use of.
You can also do it without explicit synchronization, using an AtomicBoolean:
public class MyClass{
private AtomicBoolean flag = new AtomicBoolean(false);
public void method(){
if(flag.compareAndSet(false, true)) {
//do some bulk operation, should be synchronized
}
//some other staff
}
}
This will only enter the block if nothing has entered it before, and is thread safe.
Of course, there may be other things in the block which also require synchronization. However, this works for the stated problem.
Your code looks like a perfect use case for AtomicBoolean, which has a method compareAndSet which atomically checks the value of the boolean and sets it if the check returns the expected value:
private AtomicBoolean flag = new AtomicBoolean();
public void method() {
if (flag.compareAndSet(false, true)) {
// ...
}
// other stuff
}
You can grab the object's monitor using synchronized(this){/*ToDo - synchronised code here*/}
Alternatively, you can synchronise on one of the object's fields if acquiring the object's monitor will cause concurrency issues.
This way you can use synchronized block:
synchronized(this)
{
// synchronized block
}
Don't forget about java.util.concurrent.locks.Lock, which is more powerful (and therefore, more dangerous) than Java's built-in locking. It lets you do things like this:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
final Lock myLock = new ReentrantLock();
myLock.lock();
if (...) {
...
myLock.unlock();
...
} else {
myLock.unlock();
...
}

is google volley singleton really thread safe?

In the android tranning Use a Singleton Pattern
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
I'm thinking it still not thread safey.
If Object A do getInstance and Object B do getInstance synchronously,it will still break the lock, and create two mInstance.
Because synchronized for method is only available for ONE object from different thread, but not for 2 objects.
So DO I have wrong comprehension, or below code is more safe than original?
public static synchronized MySingleton getInstance(Context context) {
synchronized(MySingleton.class)
{
if (mInstance == null) {
mInstance = new MySingleton(context);
}
}
return mInstance;
}
Your two examples do exactly the same thing.
This:
class Foobar {
static synchronized mumble(...) { doSomething(); }
}
Is just a shorthand way to write:
class Foobar {
static mumble(...) {
synchronized(Foobar.class) { doSomething(); }
}
}
A similar rule applies for non-static methods. This:
class Foobar {
synchronized mumble(...) { doSomething(); }
}
is just a shorthand way to write:
class Foobar {
mumble(...) {
synchronized(this) { doSomething(); }
}
}
I'm not sure I really understand your question, but maybe you do have "wrong comprehension".
I don't like the shortcut forms because synchronized methods draw attention away from the fact that methods are not what we want to protect with synchronization. What we want to protect is data.
We use synchronization when it is impossible for one thread to update some collection of data without creating a temporary, invalid state that other threads must not be allowed to see. We wrap a synchronized block around the code that creates the invalid state, and we also wrap synchronized blocks that synchronize on the same object around every piece of code that must not be allowed to see the invalid state.
The JVM will never allow two threads to be synchronized on the same object at the same time, so if we've done everything right, no thread will be allowed to see the invalid state except for the one that temporarily creates it.

Is it necessary to make this variable volatile?

I was going through an "JAX London 2011" presentation on "Modern Java Concurrency". Between the time duration 43:20 - 43:40, a person from the audience says the shutdown variable in the code below should have been declared as volatile and the presenters agree with it (and say that it was pointed out earlier as well, but they just didnt get to modify the presentation). The code in question is:
public abstract class QueueReaderTask implements Runnable {
private boolean shutdown = false;
protected BlockingQueue<WorkUnit<String>> lbq;
public void run() {
while (!shutdown) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
shutdown = true;
}
}
}
public abstract void doAction(String msg);
public void setQueue(BlockingQueue<WorkUnit<String>> q) { lbq = q; }
}
My Question:
I dont think that shutdown should be declared volatile.
My reasoning is that shutdown being a member of a Runnable, each task/thread will have a distinct private copy of that variable. So, why make it volatile?
But since this was discussed in JAX 2011, I am assuming there were lots of expert Java developers in that audience. I dont think all of them would have missed this !
So, what am I missing ?
P.S:-
I can understand that a variable should be declared volatile if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
each task/thread will have a distinct private copy of that variable. So, why make it 'volatile' ?
You are correct if the shutdown boolean is only modified from within the QueueReaderTask instance. In that case shutdown is only being modified by the one thread and doesn't need to be volatile.
Frankly, the code looks strange to me. Why catch InterruptedException, set the shutdown boolean, and then loop around and exit. Why now just do the following? Why have the shutdown flag at all?
while (true) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
Maybe there is extra code that was removed in the post? If not, I wonder if this was copy and pasted from a larger section of code where shutdown was set to true also in a method call.
P.S:- I can understand that a variable should be declared 'volatile' if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
Right. A typical pattern is that shutdown is modified from another thread which is telling the thread to stop processing. In that case it needs to be volatile.

Is there an alternate/better way to do this simple logic in java?

I have a method, say method1(), that takes a while to run. During it's execution, if there is another call to method1(), it should be ignored. I have, roughly, something like this
boolean mFlag = false;
void method1()
{
if(!mFlag)
{
mFlag=true;
// do Stuff
mFlag=false;
}
}
This works. But I was wondering if there is a better way to do this preferably not involving any flags.
Yes, you should really be using something from java.util.concurrent.locks Your example isn't quite strictly correct, that boolean needs to be volatile.
ReentrantLock lock = new ReentrantLock();
void method1()
{
if(lock.tryLock())
{
try {
if (!(lock.getHoldCount() > 1)) {
//do Some Stuff
}
} finally {
lock.unlock();
}
}
}
Edited to handle skipping execution on reentrance as inidicated in your comment. Unfortunatly there isn't really a great way to do that with the built in library, as it's a bit of an odd usecase, but I still think using the built in library is a better option.
Are you trying to guard against re-entry from the same thread or multiple threads accessing at the same time.
Assuming multi-threaded access, the light approach is to use java.util.concurrent.atomic. No need for anything as "heavy" as a lock (provided there are not further requirements).
Assuming no-reentry from the same method:
private final AtomicBoolean inMethod = new AtomicBoolean();
void method1() {
if (inMethod.compareAndSet(true, false)) { // Alternatively getAndSet
try {
// do Stuff
} finally {
inMethod.set(false); // Need to cover exception case!
}
}
}
If you want to allow reentry within the same thread, then it gets messy enough to use locks:
private final AtomicReference<Thread> inMethod = new AtomicReference<Thread>();
void method1() {
final Thread current = Thread.currentThread();
final Thread old = inMethod.get();
if (
old == current || // We already have it.
inMethod.compareAndSet(null, current) // Acquired it.
) {
try {
// do Stuff
} finally {
inMethod.set(old); // Could optimise for no change.
}
}
}
Could use the Execute Around idiom for this.
Maybe you should use synchronized methods
http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Categories