Java Synchronized Object? - java

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 :)

Related

Why do we need to specify the lock for synchronized statements?

Given that there's only one lock for each instance of a class, then why doesn't Java just allow us to do this:
void method() {
synchronized {
// do something
}
// do other things
}
instead of this:
void method() {
synchronized (lock) {
// do something
}
// do other things
}
What's the purpose of specifying a lock? Does it make a difference if I choose one object as a lock over the other? Or could I just choose any random object?
EDIT:
It turned out that my comprehension of synchronized methods is wrong at the fundamental level.
I thought different synchronized methods or blocks are entirely independent of each other regardless of locks. Rather, all synchronized methods or blocks with the same lock can be accessed only by one thread, even if such synchronized methods/blocks are from different classes (the documentation should have emphasized this more: ALL synced methods/blocks, regardless of location, all that matters is the lock).
Given that there's only one lock for each instance of a class, then why doesn't Java just allow us to do this:
void method() {
synchronized {
// do something
}
// do other things
}
Although an intrinsic lock is provided with each instance,
that's not necessarily the "obvious" lock to use.
You're perhaps right that they could have provided synchronized { ... } as a shorthand for synchronized (this) { ... }.
I don't know why they didn't, but I never missed it.
But concurrent programming is tricky,
so making the lock object an explicit required parameter may make things clearer to readers, which is a good thing, as #ajb pointed out in a comment.
In any case, I don't think syntax is your main question, so let's move on.
What's the purpose of specifying a lock?
Uhm, the lock is perhaps the single most important thing in the synchronization mechanism. The key point in synchronization is that only one thread can hold the same lock. Two threads holding different locks are not synchronized. So knowing what is the lock guarding the synchronization is crucial.
Does it make a difference if I choose one object as a lock over the other?
I hope the previous section makes it clear that yes, you have to choose the object carefully. It has to be an object visible by all threads involved,
it has to be not null, and it has to be something that won't get reassigned during the period of synchronization.
Or could I just choose any random object?
Certainly not. See the previous section.
To understand concurrency in Java, I recommend the book Java Concurrency in Practice by one of the authors of the API, or Oracle's tutorials on the subject.
It's so you can lock on something completely different than this.
Remember how Vector is "thread-safe?" It's not quite that simple; each call is, but code like this isn't because it could have been updated between getting the size of the vector and getting the element:
for (int i = 0; i < vector.size(); ++i) System.out.println(vector.get(i));
Since Vector, along with Collections.synchronized*, is synchronized with the older synchronized keyword, you can make that above code thread-safe by enclosing it all within a lock:
synchronized (vector) {
for (int i = 0; i < vector.size(); ++i) System.out.println(vector.get(i));
}
This could be in a method that isn't thread-safe, isn't synchronized, or uses ReentrantLock; locking the vector is separate from locking this.
It most certainly makes a difference what object you use as a lock. If you say
void method() {
synchronized (x) {
// do something
}
// do other things
}
Now, if one thread is executing the block and another tries to enter the block, if x is the same for both of them, then the second thread will have to wait. But if x is different, the second thread can execute the block at the same time. So, for example, if method is an instance method and you say
void method() {
synchronized (this) {
// do something
}
// do other things
}
Now two threads running the method using the same object can't execute the block simultaneously, but two threads can still run the method on different objects without blocking each other. This is what you'd want when you want to prevent simultaneous access to the instance variables in that object, but you don't have anything else you need to protect. It's not a problem if two threads are accessing variables in two different objects.
But say the block of code is accessing a common resource, and you want to make sure all other threads are locked out of accessing that resource. For example, you're accessing a database, and the block does a series of updates and you want to make sure they're done atomically, i.e. no other code should access the database while you're in between two updates. Now synchronized (this) isn't good enough, because you could have the method running for two different objects but accessing the same database. In this case, you'd need a lock that is the same for all objects that might access the same database. Here, making the database object itself the lock would work. Now no two threads can use method to enter this block at the same time, if they're working with the same database, even if the objects are different.
if you have multiple objects b1/b2 needs to update concurrency
class A {
private B b1, b2;
}
if you have only one lock say class A itself
synchronized (this) { ... }
then assume there are two threads are updating b1 and b2 in the same time, they will play one by one because synchronized (this)
but if you have two locks for b1 and b2
private Object lock1 = new Object, lock2 = new Object;
the two threads i've mentioned will play concurrently because synchronized (lock1) not affect synchronized (lock2).sometimes means better performance.
In synchronized (lock).., lock can be an object level lock or it can be class level lock.
Example1 Class Level Lock:
private static Object lock=new Object();
synchronized (lock){
//do Something
}
Example2 Object Level Lock:
private Object lock=new Object();
synchronized (lock){
//do Something
}

Questions about how the synchronized keyword works with locks and thread starvation

In this java tutorial there's some code that shows an example to explain the use of the synchronized keyword. My point is, why I shouldn't write something like this:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
//private Object lock1 = new Object();
//private Object lock2 = new Object();
public void inc1() {
synchronized(c1) {
c1++;
}
}
public void inc2() {
synchronized(c2) {
c2++;
}
}
}
Without bothering create lock objects? Also, why bother instantiate that lock objects? Can't I just pass a null reference? I think I'm missing out something here.
Also, assume that I've two public synchronized methods in the same class accessed by several thread. Is it true that the two methods will never be executed at the same time? If the answer is yes, is there a built-in mechanism that prevents one method from starvation (never been executed or been executed too few times compared to the other method)?
As #11thdimension has replied, you cannot synchronize on a primitive type (eg., long). It must be a class object.
So, you might be tempted to do something like the following:
Long c1 = 0;
public void incC1() {
synchronized(c1) {
c1++;
}
}
This will not work properly, as "c1++" is a shortcut for "c1 = c1 + 1", which actually assigns a new object to c1, and as such, two threads might end up in the same block of synchronized code.
For the lock to work properly, the object being synchronized upon should not be reassigned. (Well, maybe in some rare circumstances where you really know what you are doing.)
You cannot pass a null object to the synchronized(...) statement. Java is effectively creating semaphores on the ref'd object, and uses that information to prevent more than one thread accessing the same protected resource.
You do not always need a separate lock object, as in the case of a synchronized method. In this case, the class object instance itself is used to store the locking information, as if you used 'this' in the method iteslf:
public void incC1() {
synchronized(this) {
c1++;
}
}
First you can not pass primitive variable to synchronized, it requires a reference. Second that tutorial is just a example showing guarded block. It's not c1,c2 that it's trying to protect but it's trying to protect all the code inside synchronized block.
JVM uses Operating system's scheduling algorithm.
What is the JVM Scheduling algorithm?
So it's not JVM's responsibility to see if threads are starved. You can however assign priority of threads to prefer one over other to execute.
Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority. Each thread may or may not also be marked as a daemon. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.
From:https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
If you're concerned about this scenario then you have to implement it yourself. Like maintaining a thread which checks for starving threads and as time passes it increases the priority of the threads which have been waiting longer than others.
Yes it's true that two method which have been synchronized will never be executed on the same instance simultaneously.
Why bother instantiate that lock objects? Can't I just pass a null reference?
As others have mentioned, you cannot lock on long c1 because it is a primitive. Java locks on the monitor associated with an object instance. This is why you also can't lock on null.
The thread tutorial is trying to demonstrate a good pattern which is to create private final lock objects to precisely control the mutex locations that you are trying to protect. Calling synchronized on this or other public objects can cause external callers to block your methods which may not be what you want.
The tutorial explains this:
All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.
So they are also trying to allow updates to c1 and updates to c2 to happen concurrently ("interleaved") and not block each other while at the same time making sure that the updates are protected.
Assume that I've two public synchronized methods in the same class accessed by several thread. Is it true that the two methods will never be executed at the same time?
If one thread is working in a synchronized method of an object, another thread will be blocked if it tries the same or another synchronized method of the same object. Threads can run methods on different objects concurrently.
If the answer is yes, is there a built-in mechanism that prevents one method from starvation (never been executed or been executed too few times compared to the other method)?
As mentioned, this is handled by the native thread constructs from the operating system. All modern OS' handle thread starvation which is especially important if the threads have different priorities.

How to specify an object to be locked in java using Lock

Using the synchronized(intrinsic locking) keyword for locking, we could do something like:
public void addSum(int a) {
synchronized(q) {
q.add(a); // q is say a Queue
}
}
In the above code say when an object tries to call the addSum() method i.e. x.addSum(10), the lock will be held on 'q' and not x. So using synchronization we could lock an object which is other than the actual calling object(Class).
Below I'm using Lock from java concurrent package, is there a way to specify which object should the lock be on (i.e like in the above code snippet using synchronized it was specified that the lock/synchronization should be on 'q'). However below when I'm using Lock, I haven't specified on which object should the lock be on. Can it be done?
public void addSum(int a) {
lock.tryLock();
q.add(a);
lock.unlock();
}
I did refer - http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html . However was looking for much smaller example to clear my concept.
No, Lock objects don't work the same way as synchronized. synchronized cannot start within a method invocation and reach outside that method invocation. The pattern you've shown
lock.tryLock();
q.add(a);
lock.unlock();
would only be possible if the opposite were true. Lock objects typically work by flipping on/off a switch/flag atomically, indicating they've acquired or released the lock.
I think you misunderstand what the word "lock" means. Suppose this method is called:
void foobar() {
synchronized(x) {
y.doSomething();
}
}
We say that x is "locked" while the thread is in the y.doSomething() call, but that does not prevent other threads from accessing fields or updating fields of x. The synchronized keyword means one thing, and one thing only.
The JVM will not allow two threads to synchronize on the same object at the same time.
That's all it means. How you use it is up to you. My example is using it to prevent y.doSomething() from being called in more than one thread at the same time, but it only works if every call to y.doSomething() is protected in the same way, and it only works if x always refers to the same object.
The java.util.concurrent.ReentrantLock class works much the same way. The only guarantee that the JVM makes is that no two threads can "lock" the same ReentrantLock object at the same time. That's all it does. The rest is up to you.
P.S., Your second example does not test the value returned by lock.tryLock(). That's a mistake. If lock.tryLock() returns false, that means it failed to lock the lock.

What would happen with a synchronized block in a thread which is inside a synchronized method?

So basically what would happen if you have the following:
class SyncTest {
private final static List<Object> mObjectList = new ArrayList<Object>();
public synchronized void mySyncMethod(Object object) {
new Thread(new Runnable() {
public void run() {
synchronized (SyncTest.this) {
for (int i = 0; i < mObjectList.size(); i++) {
//Do something with object
}
}
}
}).start();
}
}
Say, an activity needs to run in different threads which iterates over a collection. Hence why creating a thread in the method with different objects.
Is this the "right" way, or perhaps there is a better way?
Does this present any threats?
Re-entrancy doesn't apply here. The only impact of nesting here is allowing the inner class instances to have access to the enclosing instance (including the lock being used). The two things that are synchronized are called in different threads. The new thread once created will have to get chosen by the scheduler before it can run so even though these are using the same lock it would seem unlikely there would be much overlap between the two.
The thread that calls mySyncMethod acquires the lock on the instance of SyncTest it's using, then it creates a new Thread, starts it, then releases the lock and goes on its way.
Later once the new thread starts it has to acquire the lock on the SyncTest object that started it before it can execute its run method. If the lock on SyncTest is in use by something else (either the thread that just created it, another call to mySyncMethod on the same SyncTest instance, or another thread created by another call to mySyncMethod on the same SyncTest instance) then it would have to wait around to get the lock. Then it does whatever it needs to with the list, gets to the end of the method and releases the lock.
There are a lot of problems here:
It's unclear why you need to create your own thread rather than use a pool, or why the creating method needs to synchronize and wait around for the new thread to start before it can release its lock.
The lock on the SyncTest object is not encapsulated so other things could be acquiring it, it's unclear what things are contending for the lock.
Since the list is defined as a static class member, you have more than one SyncTest object; you're going to have separate threads messing with the same list, but using different locks, so it's hard to understand what the point of locking is.
But what you've shown isn't going to deadlock.
The outer synchronized ensures single thread access to the process of creating the new Thread while the inner synchronized ensures single thread access to the for loop.
Of course you realize that as written the code doesn't make much sense because the inner this reference is targeted at your anonymous inner class. I think you really mean SyncTest.this so you are synchronizing access to the SyncTest class. Even better would be to synchronize access to mObjectList.
As written with the inner class this fixed, your Thread would block until mySyncMethod returned.
Depending on what you are doing you might be better off using one of the Concurrent collection types rather than synchronizing access to your List as you'll get better concurrency.
Nothing would happen, synchronization is with respect to the thread, so even if you re-enter the sync block many times they would not block if the owner of the sync is the same Thread.
mySyncMethod() will only run when the thread calling it can gain ownership of the lock in that instance of SyncTest.
The run method could start in its different thread, but will block on the synchronize statement until THAT thread gains ownership of the lock for the same instance of SyncTest.
(answer assumed that 'this' referred to the outer class instance, which was corrected in the edit to the original post)
If you have synchronization block inside the method then the lock is on that block only. And block inside the method can have different object's lock.

Java: What, if anything, is locked by synchronized methods apart from the object they belong to?

Now, I'm not sure whether this is a stupid question, please bear with me if it is.
Is the lock on an object "recursive", i. e. if two objects have references to a third object in their fields and a thread is running a synchronized method on one of the two, can any other thread access the third object?
// a and b are some objects that implement Runnable
// they both reference the same third object
a.ref = c;
b.ref = c;
// a is run in a thread and processes some data in a loop for a long time
// the method the loop belongs to is declared synchronized
threadA = new Thread(a);
threadA.start();
a.someSyncedMethod(); // this would block ...
b.ref.someOtherSyncedMethod(); // ... but would this?
a.ref.someOtherSyncedMethod(); // ... and how about this?
It's worth separating out the concepts of "a lock" and "locking an object". There's no real idea of "locking an object" - there's "acquiring (and releasing)" the lock associated with an object. Yes, it sounds like I'm nitpicking - but the distinction is important because if you talk about an object being locked it sounds like no other threads will be able to change anything in the object while that lock is held.
Instead, it just means that no other thread will be able to acquire the same lock while the lock is held. There's no direct relationship between the lock and any of the contents of the object that the lock is associated with.
Methods declared "synchronized" acquire the lock associated with the instance of the object they belong to. This only makes other synchronized methods on the same object wait, and synchronized statements that explicitly sync on it.
Personally I don't like synchronized methods - I like to make it clearer by explicitly synchronizing on a (private, final) member variable which is only used for synchronization.
a.someSyncedMethod(); // this would block ...
Only if you mark either the run method with synchronized or have ThreadA run code in synchronized methods.
In the JVM, each object owns what's known as a monitor. Only one thread can own the monitor associated with a given object at a time. Synchronized is the means by which you tell the current thread to go get the monitor before continuing.
Also the class itself owns a monitor for static methods.
The meaning of a "lock" (actually this variant is called a monitor) is entirely a convention, no access restrictions are enforced.
The functioning relies on all objects being well-behaved and acquiring the corresponding lock before accessing the data. Only by encapsulating this desired behaviour within in a class with proper access controls you can enforce it for the client objects.

Categories