meet IllegalMonitorStateException when doing multi-thread programming in Java - java

I wrote a simple program to learn about synchronized block. The program is as follow:
public class SychronizedBlock {
static int balance = 0;
static Integer lock = 0;
public static void deposit(int amt) {
Thread t1 = new Thread(new Runnable() {
public void run() {
acquire_lock();
int holdings = balance;
balance = holdings + amt;
System.out.println("deposit " + amt + ", balance: " + balance);
release_lock();
}
});
t1.start();
}
public static void acquire_lock() {
synchronized(lock) {
while (lock == 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock = 1;
}
}
public static void release_lock() {
synchronized(lock) {
lock = 0;
lock.notifyAll();
}
}
public static void test1() {
balance = 0;
deposit(500);
deposit(500);
}
public static void main(String[] args) {
test1();
}
}
However, when running the program, I met with an IllegalMonitorStateException. I think I have place the wait() and notifyAll() function in the synchronized block, and I have set the lock as parameter of synchronized. Why do I still have Exception?

Problem is with your release_lock method. You are reassigning lock to 0 before calling lock.notifyAll(). Which means the notifyAll will be called on a new Integer object which is not locked. Change the code to following to fix the issue.
public static void release_lock() {
synchronized(lock) {
lock.notifyAll();
lock = 0;
}
}

Related

Programme not Terminating in Multi-threaded environment -Java

Trying to make a simple multi-threaded programme where it prints Factorial series where each number is printed by different Thread and at the end I am giving a report of which number printed by which thread.I have got the desired output but somehow my program is not terminating.
Constraint: I am not allowed to use Concurrent Package
import java.util.ArrayList;
import java.util.Scanner;
class Report {
private long factorial;
private String threadName;
private int activeThreads;
public Report(long factorial, String threadName, int activeThreads) {
this.factorial = factorial;
this.threadName = threadName;
this.activeThreads = activeThreads;
}
public long getFactorial() {
return factorial;
}
public String getThreadName() {
return threadName;
}
public int getActiveThreads() {
return activeThreads;
}
public void setActiveThreads(int activeThreads) {
this.activeThreads = activeThreads;
}
}
public class Factorial implements Runnable {
public static ArrayList<Report> report = new ArrayList<Report>();
private static int count;
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("N: ");
int n = in.nextInt();
count = n;
Factorial f = new Factorial();
f.series(n);
Thread.sleep(1000);
// Series
for(Report r : report) {
if(r.getFactorial() == 1) {
System.out.print(r.getFactorial());
}
else {
System.out.print(r.getFactorial() + "*");
}
}
System.out.println();
// Report
for(Report r : report) {
System.out.println(r.getFactorial() + " printed by " + r.getThreadName() + " " + r.getActiveThreads());
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Main");
in.close();
}
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
Thread t = new Thread(new Factorial());
t.start();
}
}
public synchronized void generate() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
report.add(new Report(count--, Thread.currentThread().getName(), threadGroup.activeCount()));
notifyAll();
System.out.println("In generate" + threadGroup.activeCount());
}
#Override
public void run() {
generate();
synchronized (this) {
try {
wait();
}
catch(Exception e) {
e.printStackTrace();
}
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Run" + threadGroup.activeCount());
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
Factorial.count = count;
}
}
Although I know that we can kill the threads using .stop() but I think it's not recommended.
To make synchronization effective (synchronized, wait, notify), you have to use the same instance.
In series, you create a new Factorial instance on each loop, making every thread to wait indefinitely.
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
// Thread t = new Thread(new Factorial()); // creates an new instance
Thread t = new Thread(this);
t.start();
}
}
In the run method, you first call notifyAll() (through generate), and then wait.
The last created thread will wait after all the others are done.
One way or another, this last thread has to be notified.
It could be right after the sleep call, with:
synchronized(f) {
f.notify();
}
or maybe with a dedicated synchronized method.

print even and odd using 2 threads

Hi I am trying to print even and odd using two threads namedly EvenThread and OddThread, some times I am getting correct result and some times not, could any one please help me.
package com.java8;
public class EvenOddExample {
public static synchronized void print(int i,String name){
System.out.println(i+"--->"+name);
}
public static void main(String[] args) throws InterruptedException {
EvenThread e= new EvenThread();
e.start();
OddThread o=new OddThread();
o.start();
}
public static class EvenThread extends Thread{
public void run() {
for(int i=0;i<10;i++){
if(i%2==0){
print(i,"Even");
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public static class OddThread extends Thread{
#Override
public void run() {
for(int i=1;i<10;i++){
if(i%2!=0){
print(i,"Odd");
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
You need some signaling between the two threads. Putting synchronized on the print method simply guarantees, that only one thread can enter the method at a time. To put your threads into order Object.wait() and Object.notify{All}() methods can be used.
Actually this is some kind of the Sender-Receiver Synchronization Problem. Based on the example of the problem described here (Please read this page in order to understand how this synchronization works) I adapted your code. Additionally I used ExecutorService and Callable instead of extending Thread, which is bad-practice:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EvenOddExample {
private static boolean evensTurn = true;
private static Object monitor = new Object();
public static void print(int i, String name) {
System.out.println(i + "--->" + name);
}
public static void main(String[] args) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new EvenCallable());
executorService.submit(new OddCallable());
executorService.shutdown();
}
public static class EvenCallable implements Callable<Void> {
#Override
public Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
synchronized (monitor) {
while (!evensTurn) { // not your turn?
monitor.wait(); // wait for monitor in a loop to handle spurious wakeups
}
print(i, "Even");
evensTurn = false; // next odd needs to run
monitor.notifyAll(); // wakeup the odd thread
}
} else {
Thread.sleep(1000);
}
}
return null;
}
}
public static class OddCallable implements Callable<Void> {
#Override
public Void call() throws InterruptedException {
for (int i = 1; i < 10; i++) {
if (i % 2 != 0) {
synchronized (monitor) {
while (evensTurn) {
monitor.wait();
}
print(i, "Odd");
evensTurn = true;
monitor.notifyAll();
}
} else {
Thread.sleep(1000);
}
}
return null;
}
}
}
synchronized is used to lock the access of another thread, when the locked object is free, it does not guarantee which is next called thread. You can use semaphore to make inter-thread communication:
private static Semaphore[] semaphores = {new Semaphore(0), new Semaphore(1)};
static void print(int i, String name) {
try {
semaphores[(i + 1) % 2].acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(i + "--->" + name);
semaphores[i % 2].release();
}
public class EvenOddPrinter {
static boolean flag = true;
public static void main(String[] args) {
class Odd implements Runnable {
#Override
public void run() {
for (int i = 1; i <= 10;) {
if (EvenOddPrinter.flag) {
System.out.println(i + "--->odd");
i += 2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}
}
}
class Even implements Runnable {
#Override
public void run() {
for (int i = 2; i <= 10;) {
if (!EvenOddPrinter.flag) {
System.out.println(i + "---->even");
i += 2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}
}
}
Runnable odd = new Even();
Runnable even = new Odd();
Thread t1 = new Thread(odd, "Odd");
Thread t2 = new Thread(even, "Even");
t1.start();
t2.start();
}
}

Why is it important to make fields private when working with concurrency?

I'm reading Thinking in JAVA (Ed4, by Bruce Eckel), which says:
Note that it’s especially important to make fields private when
working with concurrency; otherwise the synchronized keyword cannot
prevent another task from accessing a field directly, and thus
producing collisions.
I am confused and finally get this demo:
public class SimpleSerial {
public static void main(String[] args) throws IOException {
ShareObject so = new ShareObject();
Thread thread1 = new Thread(new ThreadOperation(so, "add"));
Thread thread2 = new Thread(new ThreadOperation(so, "sub"));
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
System.out.println("Press Enter to stop");
System.in.read();
System.out.println("Now, a=" + so.a + " b=" + so.b);
}
}
class ThreadOperation implements Runnable {
private String operation;
private ShareObject so;
public ThreadOperation(ShareObject so, String oper) {
this.operation = oper;
this.so = so;
}
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
}
}
}
class ShareObject {
int a = 100;
int b = 100;
public synchronized void add() {
++a;
++b;
}
public synchronized void sub() {
--a;
--b;
}
}
Every time the values of a and b are different. So why?
The demo also mentioned if the thread sleep() for short time, i.e., re-write the run() method in ThreadOperation:
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
then values of a and b are the same.
So again, Why? What happens behind sleep()?
With sleep() it becomes probable that the println() executes while the threads are sleeping. The program is still very not thread-safe.
You could fix it by adding a synchronized print() method to SharedObject eg:
public synchronized void print() {
System.out.println("Now, a=" + a + " b=" + b);
}
and calling that on the last line of main instead of the current unsynchronized accesses.

non-synchronized method can access by other thread,,,,,,,

The lock on an object by one thread, no other thread can enter any of the synchronized methods in that class ,but i want to know about non-synchronized method can access by other thread,,,,,,,
class Account {
private int balance = 50;
public int getBalance() {
return balance;
}
public void withdraw(int amount) {
balance = balance - amount;
}
}
public class AccountDanger implements Runnable {
private Account acct = new Account();
public void run() {
for (int x = 0; x < 5; x++) {
this. d();
makeWithdrawal(10);
if (acct.getBalance() < 0) {
System.out.println("account is overdrawn!");
}
}
}
private synchronized void makeWithdrawal(int amt) {
if (acct.getBalance() >= amt) {
System.out.println(Thread.currentThread().getName()
+ " is going to withdraw"+amt);
try {
Thread.sleep(500);
// Thread.sleep(500);
} catch (InterruptedException ex) {
}
acct.withdraw(amt);
System.out.println(Thread.currentThread().getName()
+ " completes the withdrawal"+acct.getBalance());
} else {
System.out.println("Not enough in account for " + Thread.currentThread().getName()
+ " to withdraw " + acct.getBalance());
}
}
public static void main(String[] args) {
AccountDanger r = new AccountDanger();
Thread one = new Thread(r);
Thread two = new Thread(r);
one.setName("Fred");
two.setName("Lucy");
one.start();
two.start();
}
private void d() {
System.out.println("hhhhhhhhhhhhhhhhhhhhh"+Thread.currentThread().getName());
}
}
You have answer in your question itself :). If you are just looking for confirmation : YES.
No lock is required to access non-synchronized methods of an object.
If you want to know more about these concepts, visit Object Locks
Yes, the unsynchronized methods can be accessed/called by any Thread, that has/gets the reference to the same instance. Since you created a private Account instance and you didn't give this instance to any other class, in your example no other thread is able to access this special instance.

IllegalMonitorStateException on notify() when synchronized on an Integer

I'm new to using wait() and notify() in Java and I'm getting an IllegalMonitorStateException.
Main Code
public class ThreadTest {
private static Integer state = 0;
public static void main(String[] args) {
synchronized(state) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
synchronized(state) {
state = 0;
while(state == 0) {
try {
state.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(state) {
state = 1;
state.notify();
}
}
}
}
I'm getting an IllegalMonitorStateException what state.notify() is called. Any ideas?
Edit: Based on answer below here is code that works. As a side note, I was first trying this with an enum which has the same problem of using Integer.
public class ThreadTest {
private static int state = 0;
private static Object monitor = new Object();
public static void main(String[] args) {
synchronized(monitor) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
state = 0;
while(state == 0) {
try {
for(int i = 0; i < 5; i++) {
System.out.println("Waiting " + (5 - i) + " Seconds");
Thread.sleep(1000);
}
monitor.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(monitor) {
state = 1;
monitor.notify();
}
}
}
}
This
private static Integer state = 0;
is equivalent to
private static Integer state = Integer.valueOf(0);
The invocation of valueOf(0) returns a reference to an Integer object, call it A.
You then do
synchronized(state) {
your thread acquires the lock on the object referenced by state, currently that is A.
You then do
state = 1;
which is equivalent to
state = Integer.valueOf(1);
which gives you a different reference to an Integer object, call it B, and assigns it to state. When you then call
state.notify();
you're invoking notify() on an object, B, for which your thread doesn't own the monitor. You can't call notify or wait on objects for which your thread doesn't own the monitor.

Categories