Synchronization blocks - java

I'm a newbie to threads and specifically the synchronized key word.
I understand that a thread's state changes to BLOCKED if it tried to access a synchronized block where another thread already owns the lock.
For reference:
synchronized (objA){
objA.methodA();
}
//some code
objA.methodB();
My question is whether another thread can alter the object objA through another independent method (methodB() in this example). Or does owning the lock mean that no other thread can access/alter objA in any way ie whether or not the alteration code is within the synchronized block?

No. The only thing that owning the monitor (lock) means, is that no other thread can also own it until you give it up.
Of course, that does mean that they can't call any synchronized methods on objA (since that requires acquiring the lock), so if all of the modification methods on objA are synchronized (or use synchronized (this) {...} blocks), then the "no" becomes a "yes."
But if methodB never tries to lock on this (either by being synchronized, or by using a synchronized block), then no amount of locking on objA will block calls to objA.methodB().

Synchronizing on a object locks the monitor of the object.
It means that no synchronized method or synchronized statement on an object can be executed if a thread is already executing in a synchronized statement (or a synchronized method) on this same object.
But things are different for no synchronized methods.
Indeed, any thread may invoke any no synchronized method on objA while a thread is executing in a synchronized statement on this same objA.

Related

Java instance lock and instance field lock difference

In following code one of the thread executes A() without any interference, but after that interference occurs. Shouldn't if a thread has acquired lock on the object, it would have have acquired locks on the fields as well?
Integer i=0;
synchronized A(){
for(i=10;i>0;i--);
}
B(){
synchronized(this.i){ // if i replace this.i with this it works as expected.
for(i=10;i>0;i--);
}
}
"Shouldn't if a thread has acquired lock on the object, it would have have acquired locks on the fields as well?"
Short answer: No. The synchronized-keyword synchronizes only access to the specific object monitor (either explicitly given or implicit in case of method modifiers). It does not acquire any other locks on other objects, and does not care in any way about the values of the fields of the given object.
See also "Intrinsic Locks and Synchronization" in the official Oracle turorials.

Non-volatile variable value during wait() and notifyall() call in 2 threads

Lets say I have two threads A and B and inside these both 2 threads I have synchronized block in which an int variable is modified continously.
For example, thread A enter synchronized block modify int variable then call these 2 methods:
notifyall(); //to wake thread B which is in waiting state and
wait():
and after that thread B acquire lock and do same steps as thread A and process keep on repeating. All changes to int variable happens inside synchronized block of both threads.
My question is do I need to make int variable volatile. Do thread flush to main memory before they go to waiting state and reload data in registers when thread acquire lock again as a result of notifyall(); call.
If A and B run alternatively rather than concurrently, and if they switch off via wait() and notifyAll() invocations on the same Object, and if no other threads access the variable in question, then thread safety does not require the variable to be volatile.
Note that o.wait() and o.notifyAll() must be invoked inside a method or block synchronized on o -- that synchronization is sufficient to ensure that the two threads see all each others' writes to any variable before the switch-off.
Do be careful to ensure that the two threads are synchronizing on the same object, which is not clear from your question. You have no effective synchronization at all if, say, the two threads are waiting on and notifying different instances of the same class.
The answer is no you do not need to make the variable volatile. The reasoning being, writes that occur to a variable within a synchronized block will be visible to subsequent threads entering a synchronized block on the same object.
So it has the same memory semantics as a volatile read and write.
Not sure about java. But in C: https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt
If shared_data were declared volatile, the locking would still be
necessary. But the compiler would also be prevented from optimizing access
to shared_data within the critical section, when we know that nobody else
can be working with it. While the lock is held, shared_data is not
volatile. When dealing with shared data, proper locking makes volatile
unnecessary - and potentially harmful.

Does a thread invoking, synchronized method, pre-empt another thread using same object but in a non synchronized manner?

In Java, Does a thread invoking, synchronized method, pre-empt another thread using same object but in a non synchronized manner?
Also, when a thread is invoking a synchronized method or synchronized block, does the thread explicitly owns the entire object?
In Java, Does a thread invoking, synchronized method, pre-empt another
thread using same object but in a non synchronized manner?
No, one thread (assuming no data-races/race-conditions) knows nothing about what another thread is doing outside of synchronization.
Also, when a thread is invoking a synchronized method or synchronized
block, does the thread explicitly owns the entire object?
If by own you mean mutual exclusion, than no, it only has ownership to synchronized regions.
First question: no
Second question cannot be answered, because "owned" is not well defined.

Java Synchronized Object?

I have a class in java that reads UDP packets and puts them in an object (in a basically infinite loop). This object is then accessed in multiple separate threads, but obviously, since it is being filled at the same time, all these getters/setters are in synchronized methods. Problem is, right now these getters have code like this:
public synchronized SomeObject exampleGetter() {
if(this.isReceiving)
return oldCachedObject;
else
return currentObject;
}
Obviously, that's not quite the best way of doing things, so how should I go about writing methods (lots of different ones) that totally lock the object to one thread at a time and block the others (including the thread that created the object in the first place)? I looked at synchronized blocks, but I am kinda confused as to what effect the "lock object" has, is that the object that has access to the block at that given time? Any advice would be appreciated. Thanks!
The synchronized keyword synchronizes on the whole object instance not just the setter. I would rather go for a fine grained locking strategy or better... use a thread safe data structure where you store and get the received data. I personally love the BlockingQueue<T> where T is the type of data you receive on the network.
So suppose you are receiving Objects over a socket:
public class ReceivedDataHolder{
BlockingQueue<Object> dataBuffer = new LinkedBlockingQueue<Object>();
//...
public void dataReceived(Object data){
dataBuffer.offer(data);
}
public Object getReceivedData(){
return dataBuffer.take();
}
}
And in your socket you could do this whenever you receive data:
receivedDataHolder.dataReceived(object);
Any thread that wants to get data should do:
receivedDataHolder.getReceivedData();
This latter method call will block the calling thread until there is an element available on the queue (check this out for more details)
I hope this helps
Maybe AtomicReference would be suitable for you.
See:
java.util.concurrent.atomic
Java volatile reference vs. AtomicReference
All objects in java has something called Intrinsic locks, If any thread wants to do any operation on any object then it needs to acquire the intrinsic lock of that object. it will guarantee that only 1 thread will process your block of code at any given time.
A thread can acquire lock on any object, if that object is not locked by any other thread, if it is locked then the thread will wait till the other thread releases the lock on that object.
if you use synchronized block, your code will be somewhat like this
public void SomeObject exampleGetter() {
synchronized(this)
{
if(this.isReceiving)
return oldCachedObject;
else
return currentObject;
}
In this case when your thread enters the synchronized block, if any other thread is having lock on this object, then it will wait till that thread releases the lock. and if that object is free then your thread will acquire the lock on this object and perform the operation and then release the lock on that object.
for further information on synchronized blocks, methods and intrinsic locks, refer
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
I hope it helped you :)

Java Synchronization Lock

When we say we lock on an object using the synchronized keyword, does it mean we are acquiring a lock on the whole object or only at the code that exists in the block?
In the following example listOne.add is synchronized, does it mean if another thread accesses listOne.get it would be blocked until the first thread gets out of this block? What if a second thread accesses the listTwo.get or listTwo.add methods on the instance variables of the same object when the first thread is still in the synchronized block?
List<String> listONe = new ArrayList<String>();
List<String> listTwo = new ArrayList<String>();
/* ... ... ... */
synchronized(this) {
listOne.add(something);
}
Given the methods:
public void a(String s) {
synchronized(this) {
listOne.add(s);
}
}
public void b(String s) {
synchronized(this) {
listTwo.add(s);
}
}
public void c(String s) {
listOne.add(s);
}
public void d(String s) {
synchronized(listOne) {
listOne.add(s);
}
}
You can not call a and b at the same time, as they are locked on the same lock.
You can however call a and c at the same time (with multiple threads obviously) as they are not locked on the same lock. This can lead to trouble with listOne.
You can also call a and d at the same time, as d is no different in this context from c. It does not use the same lock.
It is important that you always lock listOne with the same lock, and allow no access to it without a lock. If listOne and listTwo are somehow related and sometimes need updates at the same time / atomically you'd need one lock for access to both of them. Otherwise 2 separate locks may be better.
Of course, you'd probably use the relatively new java.util.concurrent classes if all you need is a concurrent list :)
The lock is on the object instance that you include in the synchronized block.
But take care! That object is NOT intrinsically locked for access by other threads. Only threads that execute the same synchronized(obj), where obj is this in your example but could in other threads also be a variable reference, wait on that lock.
Thus, threads that don't execute any synchronized statements can access any and all variables of the 'locked' object and you'll probably run into race conditions.
Other threads will block only on if you have a synchronized block on the same instance. So no operations on the lists themselves will block.
synchronized(this) {
will only lock the object this. To lock and work with the object listOne:
synchronized(listOne){
listOne.add(something);
}
so that listOne is accessed one at a time by multiple threads.
See: http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html
You need to understand that the lock is advisory and is not physically enforced. For example if you decided that you where going to use an Object to lock access to certain class fields, you must write the code in such a way to actually acquire the lock before accessing those fields. If you don't you can still access them and potentially cause deadlocks or other threading issues.
The exception to this is the use of the synchronized keyword on methods where the runtime will automatically acquire the lock for you without you needing to do anything special.
The Java Language specification defines the meaning of the synchronized statement as follows:
A synchronized statement acquires a mutual-exclusion lock (ยง17.1) on behalf of the executing thread, executes a block, then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock.
SynchronizedStatement:`
synchronized ( Expression ) Block`
The type of Expression must be a reference type, or a compile-time error occurs.
A synchronized statement is executed by first evaluating the Expression.
If evaluation of the Expression completes abruptly for some reason, then the synchronized statement completes abruptly for the same reason.
Otherwise, if the value of the Expression is null, a NullPointerException is thrown.
Otherwise, let the non-null value of the Expression be V. The executing thread locks the lock associated with V. Then the Block is executed. If execution of the Block completes normally, then the lock is unlocked and the synchronized statement completes normally. If execution of the Block completes abruptly for any reason, then the lock is unlocked and the synchronized statement then completes abruptly for the same reason.
Acquiring the lock associated with an object does not of itself prevent other threads from accessing fields of the object or invoking unsynchronized methods on the object. Other threads can also use synchronized methods or the synchronized statement in a conventional manner to achieve mutual exclusion.
That is, in your example
synchronized(this) {
listOne.add(something);
}
the synchronized block does treat the object referred to by listOne in any special way, other threads may work with it as they please. However, it ensures that no other thread may enter a synchronized block for the object referred to by this at the same time. Therefore, if all code working with listOne is in synchronized blocks for the same object, at most one thread may work with listOne at any given time.
Also note that the object being locked on gets no special protection from concurrent access of its state, so the code
void increment() {
synchronized (this) {
this.counter = this.counter + 1;
}
}
void reset() {
this.counter = 0;
}
is incorrectly synchronized, as a second thread may execute reset while the first thread has read, but not yet written, counter, causing the reset to be overwritten.

Categories