Notify restricted to synchronized construct - java

I do realize that this topic has been discussed at many places. But all of them talk about it's usage in multi-threaded environment.
In this following example, why is notify() supposed to be surrounded by synchronized? It goes in vain when the keyword is used, which it is supposed to do. But why the exception, java.lang.IllegalMonitorStateException, when it is not used?
public class HelloWorld {
public static void main(String[] args) {
ABC c = new ABC();
c.put(0);
}
}
class ABC {
public synchronized void put(int value) { // why synchronized now!
System.out.println("Put: " + value);
notify();
}
}

You supposed to use synchronized is because the lock is re-entrant, meaning that it can be acquired multiple times by the same thread.
In other words if your thread already holds the lock on an object it doesn't have to wait on itself.

Related

Synchronizing static methods

I'm writing code that requires some synchronization between a few static methods. My goal is to block the execution of any of these methods if one of them executes.
So for example:
public class Foo{
static Object lock = new Object();
static List<SomeObject> listOfObjects = new ArrayList<>() ;
public static void methodA() {
synchronized (lock) {
//Do some stuff
methodB();
}
}
public static List<SomeObject> methodB() {
synchronized (lock) {
//Do some stuff
return listOfObjects;
}
}
}
Now let's assume that the following is executed from somewhere in the code:
Foo.methodA();
Foo.methodB();
My questions are:
Is it actually synchronized? will methodA and methodB won't run concurrently?
If so, will methodA calling methodB create a deadlock?
Answers:
"Is it actually synchronized? will methodA and methodB won't run
concurrently?" - yes, these methods are synchronised. More precisely, code blocks in methods are synchronised.
"If so, will methodA calling methodB create a deadlock?" - no, synchronized keyword is re-entrant in nature it means if a synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock" - from 1
You could improve code a little by providing private and final keywords:
private static final Object lock = new Object();
Also, do not return direct reference to a List you want to protect. Return read only view:
return Collections.unmodifiableList(listOfObjects);
Since now, client has only read only access which protects you from many unexpected situations.
Static versus non-static lock object in synchronized block
Object level lock vs Class level lock in Java
Is it actually synchronized? will methodA and methodB won't run
concurrently?
Yes, this synchronization looks good.
A thread can acquire the same lock multiple times, increasing a lock counter. And after it releases all of them, only then another thread can acquire that lock.
In your code, a thread calling methodA() acquires the lock twice, once in methodA() and then in methodB(). Then it releases them twice (when the synchronized blocks end).
If so, will methodA calling methodB create a deadlock?
No, as explained above, it won't create a deadlock unless you are doing some operations in those methods that can take forever to complete, in which case there will be starvation. If you are not doing any such operation, then I don't think you can get a deadlock when you are using only one lock.
Nope. Method A and method B WILL run concurrently because it's not the methods that are synchronized but the code inside. The code will continue normally with whichever has the lock. Then the other method will finish.
public class Foo1 {
static Object lock = new Object();
static List<Integer> listOfObjects = new ArrayList<>();
public static void main(String[] args) {
new Foo1().start();
}
public void start() {
new Thread(() -> methodA()).start();
// method A has the lock
sleep(1000); // sleep 1 second
// but method B is still entered and prints first
new Thread(() -> methodB()).start();
}
public static void methodA() {
sleep(5000); // sleep 5 seconds
System.out.println("Entering methodA()");
synchronized (lock) {
// Do some stuff
methodB();
}
}
public static List<Integer> methodB() {
System.out.println("Entering methodB()");
synchronized (lock) {
// Do some stuff
return listOfObjects;
}
}
static void sleep(int milli) {
try {
Thread.sleep(milli);
}
catch (InterruptedException ie) {
}
}
}

understanding nested locks in java

i want to understand this:
String string;
public Test(String string){
this.string = string;
.....
}
public void foo(newObjectPerCall o) {
synchronized (o) {
//each thread can enter here because the object passed is always different
....
synchronized (string) {
// acquire this lock if the String is free.
}
}
}
public synchronized void function() {
}
public static void main(){
Test test = new Test("hello");
for(int i = 0; i < 10;i++){
WorkerThread workerThread = new WorkerThread(test);
workerThread.start();
}
}
thread class
public class WorkerThread extends Thread {
private Test test;
public WorkerThread(Test test) {
this.test = test;
}
#Override
public void run() {
while (true) {
test.foo(new Object());
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.function();
}
}
}
my doubts are:
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes. They will block, waiting to acquire the monitor for string.
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
Yes, it's entirely independent of the other monitors. A synchronized instance method is just equivalent to one whose body is
synchronized (this) {
...
}
If no other thread already owns the monitor for this, the "new" thread can acquire it regardless of what other monitors are owned. But as all your worker threads are using the same instance of Test, only one of them will be able to be "in" function() at a time. That can be at the same time as another thread is executing foo() though.
Sorry I know only the answer only for the first question
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes

What happens when a synchronized method is called by a thread via another class?

Feels good to be a part of this community. Have read lot of answers clearing my doubts for many ques but didn't find one for this one. I know how the synchronization works in Java, but confused to see a deviated behavior when the synchronized method is being called by the the threads via another class.
PSB what I tried:
Class A with synchronzed method "meth1".
package threadinterview;
public class A {
public synchronized void meth1()
{
for(int i=0; i<3; i++)
{
System.out.println("meth1: " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + Thread.currentThread().getName());
}
}
}
Class B with non-synhronized method "meth2"
package threadinterview;
public class B {
public void meth2() {
A a1 = new A();
a1.meth1();
}
}
Main class to run the project
package threadinterview;
public class ThreadImpl {
public static void main(String[] args) {
final B b1 = new B();
final B b2 = new B();
new Thread(new Runnable() {
#Override
public void run() {
b1.meth2();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
b1.meth2();
}
}).start();
}
}
Now in this scenario, even though I am ultimately running the synchronized method, I can't see the effect of synchronization. Here what I get when I run the program:
meth1: Thread-0
meth1: Thread-1
meth1: Thread-0
meth1: Thread-1
meth1: Thread-0
meth1: Thread-1
And if I make the synchronized method static as well, then I get the class level lock and can see the synchronization effect in place. I seriously don't understand why the class level locking works but the object level doesn't work in this case.
Each call to
public void meth2() {
A a1 = new A();
a1.meth1();
}
creates a new A object. synchronized on the method synchronizes on this, the object itself. Therefore, you are synchronizing on different objects. One synchronized call doesn't prevent the other synchronized call as both threads get different monitors.
I think you are misunderstanding what the 'synchronization effect' is. In your example, you are calling B.meth2() from two separate threads. This method creates a new instance of class A and then calls A.meth1(). Now whatever locking you are trying to enforce on meth1() (which is not really clear from your example or description), it's irrelevant because you are calling it on two different instances of class A, i.e., you are implicitly using two different locks.

Why this is not right by using synchronized (Java concurrency) in this example?

I have two Java classes as below...
(1) JavaClass SyncTest: It defines a class (implementing Runnable) and invokes a "synchronized" method (named "call") defined in Class SyncTestCalled
(2) JavaClass SyncTestCalled : There is one synchronized method.
------
After calling from main(), I am thinking it should output something like:
[Two]
[Three]
[One]
But, it outputs something like this (note the open bracket which is not paired in right locations) :
[[[Two]
Three]
One]
What's wrong with the codes? Please help. Thanks a lot!
Here is the code of these two classes...
public class SyncTest implements Runnable {
Thread t;
String name;
SyncTestCalled syncTestCalled;
public SyncTest(String name) {
t = new Thread(this, name);
syncTestCalled = new SyncTestCalled();
this.name = name;
t.start();
}
public void run() {
syncTestCalled.call(this.name);
}
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest("One");
SyncTest syncTest2 = new SyncTest("Two");
SyncTest syncTest3 = new SyncTest("Three");
}
} // of class SyncTest
public class SyncTestCalled {
public SyncTestCalled() {
// Do nothing
}
synchronized public void call(String message) {
System.out.print("[");
try {
Thread.sleep(1000);
System.out.print(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("]");
}
} // of class SyncTestCalled
When you use synchronized as part of the method declaration, Java attempts to acquire the monitor (lock) on the object the method is invoked on. So a method like
synchronized public void call(String message) {
...
}
is equivalent to
public void call(String message) {
synchronized (this) {
...
}
}
In your code, you create three different SyncTestCalled objects and pass each individual one to the different SyncTest instances. In other words, nothing is coordinated. Each call to
syncTestCalled.call(this.name);
is synchronized on a different object and therefore none of the threads need to wait on the others.
It's up to the Thread scheduler who gets where first, so you get output like
[[[Two]
Three]
One]
or
[[[OneThree]
Two]
]
Note that Thread.sleep(long) does not relinquish any monitors the thread currently has.
Only one thread can invoke your call() method on a given instance at any given time. But what you want is atomicity for several calls to System.out.print() methods. For that, you need to acquire a lock on System.out instead:
synchronized (System.out) {
System.out.print('[');
System.out.print(message);
System.out.println(']');
}
Because PrintStream locks on itself, this will prevent other threads from interleaving their own calls to print().

Understanding synchronized

Given this code:
public class Messager implements Runnable {
public static void main(String[] args) {
new Thread(new Messager("Wallace")).start();
new Thread(new Messager("Gromit")).start();
}
private String name;
public Messager(String name) { this.name = name; }
public void run() {
message(1); message(2);
}
private synchronized void message(int n) {
System.out.print(name + "-" + n + " ");
}
}
I understand that the synchronized keyword makes the thread dependent on the object's lock. Questions:
a) Is the lock released as soon as the method marked as synchronized finishes? Or as soon as the thread's run() method finishes
b) Can I ensure that any one of the threads will print its name and 1 2 before the other?
A. Yes. It's released as soon as the synchronized function finishes.
B. Yes. You can, but if you wanted to do so, why would you write multithreaded code in the first place? synchronized guarantees atomicity, not anything regarding the order, but you can enforce order by waiting for a flag to change. Anyway, what you are trying to enforce is sequentiality. You get this for free in single-threaded environments :)

Categories