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

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();
...
}

Related

Java and thread safety

I am creating a mutli threaded application, and I have a question regarding the use of synchronized methods.
Lets say I have the following component which would be accessed by multiple threads.
Component.java
public class Component {
private boolean active;
//Constructor
public Component(){
active = false;
}
synchronized public void initiate(){
//do something
active = true;
}
synchronized public void closedown(){
//do something
active = false;
}
public void doSomething(){
//do something
}
public boolean isActive(){
return active;
}
}
If I have two threads accessing the the same Component object and the first thread gets halted in the Component.closedown() before it has set active = false, and the second thread picks up and calls Component.isActive(), will the second thread block until the first thread has finished the closedown, or will it get the returned value of true?
If it is the latter, how can I make this thread safe?
Yes, that is the essence of mutual-exclusion locks (mutexes). If a thread gets descheduled by the OS while holding a mutex, all other threads requiring the mutex to proceed will be stalled.
The above is actually the reason why, even if we take care to make all our critical sections very short and fast to execute, mutexes will still cause occasional latency spikes, and the spikes will be huge in proportion to regular latency. For example, your simple getter will execute in a couple of nanoseconds when uncontended, but may take 10µs or more if the thread holding the mutex is descheduled at an inconvenient time.
NOTE: The code in your question lacks the synchronized designation on isActive, but I assume your question is about what would happen if it was synchronized—because the code has a data race without it. Specifically:
will the second thread block until the first thread has finished the closedown, or will it get the returned value of true?
Without synchronized it will do neither: it won't block, but it won't be guaranteed to ever return the true value. You are only guaranteed to observe the initial value (that's what the data race is about).
If you are looking for a practical advice to improve your code, then don't synchronize isActive method, but make the active flag volatile. This is standard practice for your use case.
You need to have use a lock to protect the critical sections. As some methods read from the value and some write to the value, you can try using a ReadWriteLock.
public class Component {
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private boolean active;
//Constructor
public Component(){
active = false;
}
public void initiate(){
// non-critical section
rwl.writeLock().lock();
try {
// critical section
active = true;
} finally {
rwl.writeLock().unlock();
}
}
public void closedown(){
// non-critical section
rwl.writeLock().lock();
try {
// critical section
active = false;
} finally {
rwl.writeLock().unlock();
}
}
public void doSomething(){
// do something
}
public boolean isActive(){
rwl.readLock().lock();
boolean status = active;
rwl.readLock().unlock();
return status;
}
}

How to conditionally disable a synchronized block in 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(...) {
...
}

Why not using a try with lock in java?

I've read this topic, and this blog article about try with resources locks, as the question popped in my head.
But actually, what I'd rather like would be a try with lock, I mean without lock instantiation. It would release us from the verbose
lock.lock();
try {
//Do some synchronized actions throwing Exception
} finally {
//unlock even if Exception is thrown
lock.unlock();
}
Would rather look like :
? implements Unlockable lock ;
...
try(lock) //implicitly calls lock.lock()
{
//Do some synchronized actions throwing Exception
} //implicitly calls finally{lock.unlock();}
So it would not be a TWR, but just some boilerplate cleaning.
Do you have any technical reasons to suggest describing why this would not be a reasonable idea?
EDIT : to clarify the difference between what I propose and a simple synchronized(lock){} block, check this snippet :
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ReentrantLock locker =new ReentrantLock();
Condition condition = locker.newCondition();
Thread t1 = new Thread("Thread1") {
#Override
public void run(){
synchronized(locker){
try {
condition.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread1 finished");
}
}
} ;
Thread t2 = new Thread("Thread2") {
#Override
public void run(){
synchronized(locker){
Thread.yield();
condition.signal();
System.out.println("blabla2");
}
}
} ;
t1.start();
t2.start();
}
}
Execution will result in a IllegalMonitorStateException, so lock() and unlock() methods are not implicitly called within synchronized block.
If you had to deal with a simple case like that, where the pattern of locking/unlocking was limited to a narrow scope like this, you probably don't want to use the more complicated Lock class and probably should just be using the synchronized keyword, instead. That being said, if for some reason you needed this with the more complicated Lock object, it should be relatively straight-forward to create a wrapper around Lock that implements the AutoCloseable interface to be able to do just that. Example:
class AutoUnlock implements AutoCloseable {
private final Lock lock;
public static AutoUnlock lock(Lock lock) {
lock.lock();
return new AutoUnlock(lock);
}
public static AutoUnlock tryLock(Lock lock) {
if (!lock.tryLock()) {
throw new LockNotAcquiredException();
}
return new AutoUnlock(lock);
}
#Override
public void close() {
lock.unlock();
}
private AutoUnlock(Lock lock) {
this.lock = lock;
}
}
With a wrapper like the above, you could then do:
try (AutoUnlock autoUnlock = AutoUnlock.lock(lock)) {
// ... do whatever that requires the lock ...
}
That being said, the Lock class is typically used for very complicated locking scenarios where this wouldn't be particularly useful. For example, Lock objects may be locked in one function in a class and later unlocked in another function (e.g. locking a row in a database in response to an incoming remote procedure call, and then unlocking that row in response to a later RPC), and thus having such a wrapper or making a Lock AutoCloseable, itself, would be of limited use for the way it is actually used. For more simple scenarios, it's more common to just use an existing concurrent datastructure or use synchronized.
This answer serves to explain the behavior of your edit. The purpose of synchronized is to lock the monitor of the given object when the thread enters the block (waiting if it isn't available) and releasing it when the thread exits the block.
Lock is a higher level abstraction.
Lock implementations provide more extensive locking operations than
can be obtained using synchronized methods and statements.
You can use it to lock across method boundaries. synchronized is not able to do this so a Lock cannot be implemented solely with synchronized and no implementation I've ever seen uses it. Instead, they use other patterns, like compare and swap. They use this to set a state atomically within a Lock object which marks a certain thread as the owner of the lock.
In your code snippet, you try to invoke
condition.signal();
in a thread which does not own the Lock from which the condition was created. The javadoc states
An implementation may (and typically does) require that the current
thread hold the lock associated with this Condition when this method
is called. Implementations must document this precondition and any
actions taken if the lock is not held. Typically, an exception such as
IllegalMonitorStateException will be thrown.
That's what happened here.
Executing
synchronized (lock) {}
makes the current thread lock (and then release) the monitor on the object referenced by lock. Executing
lock.lock();
makes the current thread set some state within the object referenced by lock which identifies it as the owner.

One thread updates variable and another read it, do I need something special

I have a class that has the object "Card". This class keeps checking to see if the object is not null anymore. Only one other thread can update this object. Should I just do it like the code below? Use volatile?Syncronized? lock (which I dont know how to use really)? What do you recommend as easiest solution?
Class A{
public Card myCard = null;
public void keepCheck(){
while(myCard == null){
Thread.sleep(100)
}
//value updated
callAnotherMethod();
}
Another thread has following:
public void run(){
a.myCard = new Card(5);
}
What do you suggest?
You should use a proper wait event (see the Guarded Block tutorial), otherwise you run the risk of the "watching" thread seeing the reference before it sees completely initialized member fields of the Card. Also wait() will allow the thread to sleep instead of sucking up CPU in a tight while loop.
For example:
Class A {
private final Object cardMonitor = new Object();
private volatile Card myCard;
public void keepCheck () {
synchronized (cardMonitor) {
while (myCard == null) {
try {
cardMonitor.wait();
} catch (InterruptedException x) {
// either abort or ignore, your choice
}
}
}
callAnotherMethod();
}
public void run () {
synchronized (cardMonitor) {
myCard = new Card(5);
cardMonitor.notifyAll();
}
}
}
I made myCard private in the above example. I do recommend avoiding lots of public fields in a case like this, as the code could end up getting messy fast.
Also note that you do not need cardMonitor -- you could use the A itself, but having a separate monitor object lets you have finer control over synchronization.
Beware, with the above implementation, if run() is called while callAnotherMethod() is executing, it will change myCard which may break callAnotherMethod() (which you do not show). Moving callAnotherMethod() inside the synchronized block is one possible solution, but you have to decide what the appropriate strategy is there given your requirements.
The variable needs to be volatile when modifying from a different thread if you intend to poll for it, but a better solution is to use wait()/notify() or even a Semaphore to keep your other thread sleeping until myCard variable is initialized.
Looks like you have a classic producer/consumer case.
You can handle this case using wait()/notify() methods. See here for an example: How to use wait and notify in Java?
Or here, for more examples: http://www.programcreek.com/2009/02/notify-and-wait-example/

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