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.
Related
I am using multi-threading in java for my program.
I have run thread successfully but when I am using Thread.wait(), it is throwing java.lang.IllegalMonitorStateException.
How can I make a thread wait until it will be notified?
You need to be in a synchronized block in order for Object.wait() to work.
Also, I recommend looking at the concurrency packages instead of the old school threading packages. They are safer and way easier to work with.
EDIT
I assumed you meant Object.wait() as your exception is what happens when you try to gain access without holding the objects lock.
wait is defined in Object, and not it Thread. The monitor on Thread is a little unpredictable.
Although all Java objects have monitors, it is generally better to have a dedicated lock:
private final Object lock = new Object();
You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:
private static final class Lock { }
private final Object lock = new Lock();
In order to wait or notify/notifyAll an object, you need to be holding the lock with the synchronized statement. Also, you will need a while loop to check for the wakeup condition (find a good text on threading to explain why).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
It is well worth getting to understand both Java language and java.util.concurrent.locks locks (and java.util.concurrent.atomic) when getting into multithreading. But use java.util.concurrent data structures whenever you can.
I know this thread is almost 2 years old but still need to close this since I also came to this Q/A session with same issue...
Please read this definition of illegalMonitorException again and again...
IllegalMonitorException is thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
This line again and again says, IllegalMonitorException comes when one of the 2 situation occurs....
1> wait on an object's monitor without owning the specified monitor.
2> notify other threads waiting on an object's monitor without owning the specified monitor.
Some might have got their answers... who all doesn't, then please check 2 statements....
synchronized (object)
object.wait()
If both object are same... then no illegalMonitorException can come.
Now again read the IllegalMonitorException definition and you wont forget it again...
Based on your comments it sounds like you are doing something like this:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
There are three problems.
As others have said, obj.wait() can only be called if the current thread holds the primitive lock / mutex for obj. If the current thread does not hold the lock, you get the exception you are seeing.
The thread.wait() call does not do what you seem to be expecting it to do. Specifically, thread.wait() does not cause the nominated thread to wait. Rather it causes the current thread to wait until some other thread calls thread.notify() or thread.notifyAll().
There is actually no safe way to force a Thread instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecated Thread.suspend() method, but that method is inherently unsafe, as is explained in the Javadoc.)
If you want the newly started Thread to pause, the best way to do it is to create a CountdownLatch instance and have the thread call await() on the latch to pause itself. The main thread would then call countDown() on the latch to let the paused thread continue.
Orthogonal to the previous points, using a Thread object as a lock / mutex may cause problems. For example, the javadoc for Thread::join says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?
Are you calling Thread.wait() from within the thread, or outside it?
I ask this because according to the javadoc for IllegalMonitorStateException, it is:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:
private static final class Lock { }
private final Object lock = new Lock();
#Test
public void testRun() {
ThreadWorker worker = new ThreadWorker();
System.out.println ("Starting worker");
worker.start();
System.out.println ("Worker started - telling it to wait");
try {
synchronized (lock) {
worker.wait();
}
} catch (InterruptedException e1) {
String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
System.out.println (msg);
e1.printStackTrace();
System.out.flush();
}
System.out.println ("Worker done waiting, we're now waiting for it by joining");
try {
worker.join();
} catch (InterruptedException ex) { }
}
In order to deal with the IllegalMonitorStateException, you must verify that all invocations of the wait, notify and notifyAll methods are taking place only when the calling thread owns the appropriate monitor. The most simple solution is to enclose these calls inside synchronized blocks. The synchronization object that shall be invoked in the synchronized statement is the one whose monitor must be acquired.
Here is the simple example for to understand the concept of monitor
public class SimpleMonitorState {
public static void main(String args[]) throws InterruptedException {
SimpleMonitorState t = new SimpleMonitorState();
SimpleRunnable m = new SimpleRunnable(t);
Thread t1 = new Thread(m);
t1.start();
t.call();
}
public void call() throws InterruptedException {
synchronized (this) {
wait();
System.out.println("Single by Threads ");
}
}
}
class SimpleRunnable implements Runnable {
SimpleMonitorState t;
SimpleRunnable(SimpleMonitorState t) {
this.t = t;
}
#Override
public void run() {
try {
// Sleep
Thread.sleep(10000);
synchronized (this.t) {
this.t.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
You ask
How can I make a thread wait until it will be notified?
You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
Details for synchronization and waiting are already explained by Tom Hawtin.
java.lang.IllegalMonitorStateException means you are trying to wait on object on which you are not synchronized - it's illegal to do so.
Not sure if this will help somebody else out or not but this was the key part to fix my problem in user "Tom Hawtin - tacklin"'s answer above:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
Just the fact that the "lock" is passed as an argument in synchronized() and it is also used in "lock".notifyAll();
Once I made it in those 2 places I got it working
I received a IllegalMonitorStateException while trying to wake up a thread in / from a different class / thread. In java 8 you can use the lock features of the new Concurrency API instead of synchronized functions.
I was already storing objects for asynchronous websocket transactions in a WeakHashMap. The solution in my case was to also store a lock object in a ConcurrentHashMap for synchronous replies. Note the condition.await (not .wait).
To handle the multi threading I used a Executors.newCachedThreadPool() to create a thread pool.
Those who are using Java 7.0 or below version can refer the code which I used here and it works.
public class WaitTest {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitHere(long waitTime) {
System.out.println("wait started...");
lock.lock();
try {
condition.await(waitTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
System.out.println("wait ends here...");
}
public static void main(String[] args) {
//Your Code
new WaitTest().waitHere(10);
//Your Code
}
}
For calling wait()/notify() on object, it needs to be inside synchronized block. So first you have to take lock on object then would be possible to call these function.
synchronized(obj)
{
obj.wait()
}
For detailed explanation:
https://dzone.com/articles/multithreading-java-and-interviewspart-2
wait(), notify() and notifyAll() methods should only be called in syncronized contexts.
For example, in a syncronized block:
syncronized (obj) {
obj.wait();
}
Or, in a syncronized method:
syncronized static void myMethod() {
wait();
}
class Common
{
public synchronized void synchronizedMethod1()
{
System.out.println("synchronized Method1 called");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("synchronized Method1 done");
}
public synchronized void synchronizedMethod2()
{
System.out.println("synchronized Method2 called");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("synchronized Method2 done");
}
}
In the above class I have two synchronized methods which I am calling from run method of another class. Other class code is given below:
public class ThreadClass implements Runnable
{
private int id = 0;
private Common common;
public ThreadClass(int no, Common object)
{
common = object;
id = no;
}
public void run()
{
System.out.println("Running Thread " + Thread.currentThread().getName());
try
{
if (id == 11)
{
common.synchronizedMethod1();
}
else
{
common.synchronizedMethod2();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
Common c = new Common();
ThreadClass tc = new ThreadClass(11, c);
ThreadClass tc1 = new ThreadClass(20, c);
Thread t1 = new Thread(tc, "Thread 1");
Thread t2 = new Thread(tc1, "Thread 2");
t1.start();
t2.start();
}
}
From main method I am starting two different threads. In run method I have given a condition to send both different threads to different synchronized methods. Output produced by the code is:
Running Thread Thread 2
Running Thread Thread 1
synchronized Method2 called
synchronized Method2 done
synchronized Method1 called
synchronized Method1 done
MY QUESTION FOR THE OUTPUT IS:
When thread 2 goes to synchronized Method2 it prints 3rd line of output and goes to sleep for 1 second. Now since thread 1 is not blocked by anything so it should execute and print 5th line of the output just after 3rd line of output and should go to sleep then but this is not happening instead when thread 2 goes to sleep it make's thread 1 also sleep then first thread 2 complete's its execution after which thread 1 completes its execution.
Such a behavior is not happening if I remove synchronized keyword from methods.
Can you please explain me the reason behind different way of processing the code with and without synchronized keywords.
Thanks in advance.
Such a behavior is not happening if I remove synchronized keyword from methods. Can you please explain me the reason behind different way of processing the code with and without synchronized keywords.
This is actually the entire purpose of the synchronized keyword. When you have several synchronized instance methods of the same class, only one may be executing at a time. You have written this:
class Common {
public synchronized void synchronizedMethod1(){}
public synchronized void synchronizedMethod2(){}
}
Because both methods are synchronized, only one may be executed at once. One of them can't start the other one is done.
How does this work? In short, you have a Common object and call a synchronized instance method of it. When you call synchronzedMethod1, that method will "lock" the Common object (called "acquiring the lock"). While that method has that lock on that Common object, if you try to call any other synchronized method on that same object, it will try to lock it and it will find that it's already locked. So any other attempt to lock the object will hang until they can do so. Once synchronizedMethod1 finishes, it will unlock the Common object (called "releasing the lock") and anybody can then try to lock it, such as synchronzedMethod2.
So in short, synchronized specifically makes it so you can't have two synchronized methods of the same class happening at once. This is useful because some problematic behavior can come from not doing this. As an example, ArrayList does not do this, so if one thread tries to add an object to an ArrayList while another tries to iterate over it, it might throw a ConcurrentModificationException and make everyone sad.
A sleeping thread does not release its locks, but you can replace your sleep(...) calls with wait(...). Keep in mind, though, that only the lock of the object having wait(...) called on it will be released, so you'd have to devise a different solution if you expected multiple locks to be released while waiting.
synchronising a method doesnt mean just the method itself synchronised
synchronized void x(){}
equals to:
void x(){
synchronised(this){}
}
Since both thread access same Common instance first thread will get the ownership of the Common object lock doesnt matter which synchronised method called and it will just release this lock after this method body completed its job.
If you would send two Common instance there would not be a problem since they are not static. Also you might be interested in ReentrantLock
First of all synchronized keyword is used to define mutual exclusion. Here mutual exclusion achieved by Monitor concept. One more thing is sleep does not release monitor. It just pause the execution of current thread for some time. Other threads which requires the monitor have to wait until the thread which acquired monitor release it.
There is two ways to use synchronized...
First one is using synchronized blocks.
synchronized(obj){...}
Here if any thread want to enter into synchronized block it have to get monitor of obj.
Second one is to using synchronized method.
synchronized void meth(){...}
Main difference between synchronised method & block is synchronised method use monitor of object it self & synchronised block can have monitor of any object.
Synchronized method can be defined using synchronized block as follows...
void meth(){
synchronized (this){
//method body
}
}
Now you can use the synchronised block to prevent the problem of blocking another method. Here you have to define synchronised block on different objects so both methods can execute concurrently but multiple threads can not execute same method concurrently.
I've wrote some multithreading code in java and synchronized method that changed variable, but it doesn't synchronized my code, I still get random values. There is my code:
public class Main {
public static void main(String[] args) throws Exception {
Resource.i = 5;
MyThread myThread = new MyThread();
myThread.setName("one");
MyThread myThread2 = new MyThread();
myThread.start();
myThread2.start();
myThread.join();
myThread2.join();
System.out.println(Resource.i);
}
}
class MyThread extends Thread {
#Override
public void run() {
synMethod();
}
private synchronized void synMethod() {
int i = Resource.i;
if(Thread.currentThread().getName().equals("one")) {
Thread.yield();
}
i++;
Resource.i = i;
}
}
class Resource {
static int i;
}
Sometimes I get 7, sometimes 6, but I've synchronized synMethod, as I understand no thread should go at this method while some other thread executing this, so operations should be atomic, but they are not, and I can't understand why? Could you please explain it to me, and answer - how can I fix it?
Adding the synchronized method is like synchronizing on this. Since you have two different instances of threads, they don't lock each other out, and this synchronization doesn't really do anything.
In order for synchronization to take effect, you should synchronize on some shared resource. In your example, Resource.class could by a good choice:
private void synMethod() { // Not defined as synchronized
// Synchronization done here:
synchronized (Resource.class) {
int i = Resource.i;
if (Thread.currentThread().getName().equals("one")) {
Thread.yield();
}
i++;
Resource.i = i;
}
}
Let's have a look at definition of synchronized methods from oracle documentation page.
Making the 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.
Coming back to your query:
synMethod() is a synchronized method object level. Two threads accessing same synchronized method acquire the object lock in sequential manner. But two threads accessing synchronized method of different instances (objects) run asynchronously in the absence of shared lock.
myThread and myThread2 are two different objects => The intrinsic locks are acquired in two different objects and hence you can access these methods asynchronously.
One solution : As quoted by Mureinik, use shared object for locking.
Other solution(s): Use better concurrency constructs like ReentrantLock etc.
You find few more alternatives in related SE question:
Avoid synchronized(this) in Java?
I am new to java learning the concepts of threading in java , i was planing to answer the following below questions
class Deadlocker
{
void executedByThreadOne();
void executedByThreadTwo();
}
Provide simple implementation of class Deadlocker above such that if the two methods are called concurrently by different threads, there will be chance of a deadlock.
folks please advise how such can we design class in java
Read some literature on deadlocks and think about, how to achieve this in a fake environment.
As a hint, you will propably need Thread.sleep to have your locks "overlapping". Imagine your locking process like an "x". Thread 1 is locking A, then sleeps, then locking B. But, while Thread 1 is sleeping, Thread B has to lock B and then try to lock A (which is already locked by A). Then you have your deadlock.
One source that can cause deadlock are locks. If you call method1 from one thread and method2 from the other, there will be a big chance of getting a deadlock:
Object lock1 = ...;
Object lock2 = ... ;
public void method1(){
synchronized (lock1) {
Thread.sleep(100);
synchronized (lock2) {
System.out.println("Acquired both locks");
}
}
}
public void method2(){
synchronized (lock2) {
Thread.sleep(100);
synchronized (lock1) {
System.out.println("Acquired both locks");
}
}
}
The above illustrates what is known as lock‐ordering deadlocks.
If I synchronized two methods on the same class, can they run simultaneously on the same object? For example:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
I know that I can't run methodA() twice on same object in two different threads. same thing in methodB().
But can I run methodB() on different thread while methodA() is still running? (same object)
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).
In the example methodA and methodB are instance methods (as opposed to static methods). Putting synchronized on an instance method means that the thread has to acquire the lock (the "intrinsic lock") on the object instance that the method is called on before the thread can start executing any code in that method.
If you have two different instance methods marked synchronized and different threads are calling those methods concurrently on the same object, those threads will be contending for the same lock. Once one thread gets the lock all other threads are shut out of all synchronized instance methods on that object.
In order for the two methods to run concurrently they would have to use different locks, like this:
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
where the synchronized block syntax allows specifying a specific object that the executing thread needs to acquire the intrinsic lock on in order to enter the block.
The important thing to understand is that even though we are putting a "synchronized" keyword on individual methods, the core concept is the intrinsic lock behind the scenes.
Here is how the Java tutorial describes the relationship:
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
The purpose of locking is to protect shared data. You would use separate locks as shown in the example code above only if each lock protected different data members.
Java Thread acquires an object level lock when it enters into an instance synchronized java method and acquires a class level lock when it enters into static synchronized java method.
In your case, the methods(instance) are of same class. So when ever a thread enters into java synchronized method or block it acquires a lock(the object on which the method is called). So other method cannot be called at the same time on the same object until the first method is completed and lock(on object) is released.
In your case you synchronized two method on the same instance of class. So, these two methods can't run simultaneously on different thread of the same instance of class A. But they can on different class A instances.
class A {
public synchronized void methodA() {
//method A
}
}
is the same as:
class A {
public void methodA() {
synchronized(this){
// code of method A
}
}
}
Think of your code as the below one:
class A {
public void methodA() {
synchronized(this){
//method A body
}
}
public void methodB() {
synchronized(this){
// method B body
}
}
So, synchronized on method level simply means synchronized(this).
if any thread runs a method of this class, it would obtain the lock before starting the execution and hold it until the execution of the method is finished.
But can I run methodB() on different thread while methodA() is still
running? (same object)
Indeed, it is not possible!
Hence, multiple threads will not able to run any number of synchronized methods on the same object simultaneously.
From oracle documentation link
Making 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
This will answer your question: On same object, You can't call second synchronized method when first synchronized method execution is in progress.
Have a look at this documentation page to understand intrinsic locks and lock behavior.
Just to all clarity, It’s possible that both static synchronized and non static synchronized method can run simultaneously or concurrently because one is having object level lock and other class level lock.
The key idea with synchronizing which does not sink in easily is that it will have effect only if methods are called on the same object instance - it has already been highlighted in the answers and comments -
Below sample program is to clearly pinpoint the same -
public class Test {
public synchronized void methodA(String currentObjectName) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA in");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA out");
}
public synchronized void methodB(String currentObjectName) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB in");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB out");
}
public static void main(String[] args){
Test object1 = new Test();
Test object2 = new Test();
//passing object instances to the runnable to make calls later
TestRunner runner = new TestRunner(object1,object2);
// you need to start atleast two threads to properly see the behaviour
Thread thread1 = new Thread(runner);
thread1.start();
Thread thread2 = new Thread(runner);
thread2.start();
}
}
class TestRunner implements Runnable {
Test object1;
Test object2;
public TestRunner(Test h1,Test h2) {
this.object1 = h1;
this.object2 = h2;
}
#Override
public void run() {
synchronizedEffectiveAsMethodsCalledOnSameObject(object1);
//noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(object1,object2);
}
// this method calls the method A and B with same object instance object1 hence simultaneous NOT possible
private void synchronizedEffectiveAsMethodsCalledOnSameObject(Test object1) {
try {
object1.methodA("object1");
object1.methodB("object1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// this method calls the method A and B with different object instances object1 and object2 hence simultaneous IS possible
private void noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(Test object1,Test object2) {
try {
object1.methodA("object1");
object2.methodB("object2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Notice the difference in output of how simultaneous access is allowed as expected if methods are called on different object instances.
Ouput with noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects() commented -the output is in order methodA in > methodA Out .. methodB in > methodB Out
and Ouput with synchronizedEffectiveAsMethodsCalledOnSameObject() commented -
the output shows simultaneous access of methodA by Thread1 and Thread0 in highlighted section -
Increasing the number of threads will make it even more noticeable.
You are synchronizing it on object not on class. So they cant run simultaneously on the same object
No it is not possible, if it were possible then both method could be updating same variable simultaneously which could easily corrupt the data.
Yes, they can run simultaneously both threads. If you create 2 objects of the class as each object contains only one lock and every synchronized method requires lock.
So if you want to run simultaneously, create two objects and then try to run by using of those object reference.
Two different Threads executing a common synchronized method on the single object, since the object is same, when one thread uses it with synchronized method, it will have to verify the lock, if the lock is enabled, this thread will go to wait state, if lock is disabled then it can access the object, while it will access it will enable the lock and will release the lock
only when it's execution is complete.
when the another threads arrives, it will verify the lock, since it is enabled it will wait till the first thread completes his execution and releases the lock put on the object, once the lock is released the second thread will gain access to the object and it will enable the lock until it's execution.
so the execution will not be not concurrent, both threads will execute one by one, when both the threads use the synchronized method on different objects, they will run concurrently.