illegalMonitorException while printing odd even numbers using 2 different threads - java

Following is my code to print odd even number using 2 different threads.
But while running the code, i am getting IllegalMonitorException.
Please help me to understand why I am getting this exception.
class PrintOddEven {
public static void main(String args[]) {
Integer num = new Integer(1);
Thread odd = new Thread(new Odd(num));
Thread even = new Thread(new Even(num));
odd.start();
even.start();
}
}
class Odd implements Runnable {
Integer num;
public Odd(Integer num) {
super();
this.num = num;
}
#Override
public void run() {
while (num <= 100) {
try {
synchronized (num) {
if (num % 2 == 0) {
num.wait();
}
System.out.println(num);
num++;
num.notifyAll();
num.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Even implements Runnable {
Integer num;
public Even(Integer num) {
super();
this.num = num;
}
#Override
public void run() {
while (num <= 100) {
try {
synchronized (num) {
if (num % 2 != 0) {
num.wait();
}
System.out.println(num);
num++;
num.notifyAll();
num.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Please help me to understand why this code is throwing illegalMonitorException

Integer num = new Integer(1);
System.out.println(num.hashCode());
num++;
System.out.println(num.hashCode());
If you execute this piece of code then you will find hashcode is different (which is their value i.e. 1 and 2) so if hashcode is different then how could it be same object (as pointed out by #Nathan Hughes). So that is the reason you're getting java.lang.IllegalMonitorStateException
import java.util.concurrent.atomic.AtomicInteger;
class PrintOddEven {
public static void main(String args[]) {
AtomicInteger num = new AtomicInteger(1);
Thread odd = new Thread(new Odd(num));
Thread even = new Thread(new Even(num));
odd.start();
even.start();
}
}
class Odd implements Runnable {
AtomicInteger num;
public Odd(AtomicInteger num) {
super();
this.num = num;
}
#Override
public void run() {
while (num.get() < 100) {
try {
synchronized (num) {
if (num.get() % 2 == 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Even implements Runnable {
AtomicInteger num;
public Even(AtomicInteger num) {
super();
this.num = num;
}
#Override
public void run() {
while (num.get() <= 100) {
try {
synchronized (num) {
if (num.get() % 2 != 0) {
num.wait();
}
System.out.println(num);
num.getAndIncrement();
num.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Integer objects are immutable. When you change its value you're replacing the object being referenced by the variable with a new instance. A thread acquires the lock on the object referenced by num, then increments the number, thereby replacing the object with another one. Then the thread calls notifyAll on the object referenced by num, which is a different object from the one that it acquired the lock on. You're not allowed to do that, that's what the IllegalMonitorStateException is telling you.
TLDR: the lock isn't on a variable, it's on an object. Incrementing the value of an immutable object swaps that object out for a different object where nothing has acquired its lock.
Use a dedicated lock that you don't use for anything else, and pass that to your Odd and Even objects.

Related

How do I instantiate two threads of the same object, and have the objects print different things

The goal: So I have a runnable class ThisThat. I instantiate two threads of ThisThat. One prints "This" and one prints "That". The main class is not supposed to determine what it prints.
The question: how do I make a default constructor set two different outputs for two threads of the same class? What can be improved? How can I make it only print this or that instead of both simultaneously?
Desired end result would be a program that runs for about 10 seconds and prints either this or that 10 times. Current output is "this" "that" at the same time, waits about 10 seconds and then repeats 10 times.
import java.util.Random;
public class ThisThat implements Runnable {
private String output;
private int threadNum;
public ThisThat() {
output = "";
}
public ThisThat(int t_Num) {
threadNum = t_Num;
setThisOrThat(threadNum);
}
public void setThisOrThat(int num) {
if (num == 1) {
output = "this";
} else if (num == 2) {
output = "that";
} else {
Random random = new Random();
int randNum = random.nextInt((3) + 1);
setThisOrThat(randNum);
}
}
#Override
public void run() {
for (int i=1; i <= 10; i++) {
try {
System.out.println(getOutput());
Thread.sleep((int)(800));
}
catch(InterruptedException e) {
System.err.println(e);
}
}
}
public String getOutput() { return output; }
public void setOutput(String output) { this.output = output; }
}
class Main {
public static void main(String args[]) {
Thread thread1 = new Thread(new ThisThat(1));
Thread thread2 = new Thread(new ThisThat(2));
thread1.start();
thread2.start();
}
}
One solution is to update the constructor to not take in anything from Main, then create a static volatile or Atomic property within your ThisThat class that is basically a counter changing the values for each thread instance.

Thread safe read/write to a counter

Im trying to make 2 threads that read/write to a counter using thread safe methods.
I have written some code to try test this but the read thread just reads the counter at its max (1000)
Main:
public static void main(String[] args) {
Counter c = new Counter();
Thread inc = new Increment(c);
Thread read = new Read(c);
inc.start();
read.start();
}
Counter:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public synchronized void increment() {
count++;
}
public synchronized int getVal() {
return count;
}
}
Increment:
public class Increment extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Increment(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
myCounter.increment();
}
}
}
Read:
public class Read extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Read(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
System.out.println(myCounter.getVal());
}
}
}
Would I be better off using Atomic Integer to hold the value of the counter to allow me to safely increment it and get the value?
Your code is perfectly fine as is. It just so happened that your increment thread finished all its increments before the read thread got a chance to read. 1,000 increments takes almost no time at all.
If you want interleave execution of Read thread and Increment thread much more often then the natural operating system thread pre-emption, just make each thread give up their lock (by calling <lockedObject>.wait() followed by <lockedObject>.notify() or notifyAll() in the respective run() methods:
[In Reader]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
System.out.println(myCounter.getVal());
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[In Increment]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
myCounter.increment();
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Upping the MAX constant to 1_000_000_000 (1 billion) made the treads interleave as well every now and then (on my machine interleave happened just by gazing at few printouts between 150 and 400_000 iterations).

synchronized keyword does not work as expected in java [duplicate]

This question already has answers here:
synchronized block for an Integer object
(3 answers)
Closed 6 years ago.
Edit:
I have already found the answer on the stack:
https://stackoverflow.com/a/16280842/3319557
I face a problem with synchronization. I have two following methods:
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
synchronized (counter) {
counter++;
}
}
I test each of those (separately) in many threads. First method behaves as expected, but second (incrementCounter2) is wrong. Can somebody explain why is this happening?
I assume this method is well designed, as I found something lookalike in Java Concurrency in Practice. Snipped from this book:
#ThreadSafe
public class ListHelper<E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
...
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
}
I use monitor from the Object I am modifying, exactly like in book.
Full code here:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizationTest {
public static final int N_THREADS = 500;
public static final int N_Loops = 5000;
private Integer counter = 0;
Lock l = new ReentrantLock();
public void incrementCounter0() {
counter++;
}
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
synchronized (counter) {
counter++;
}
}
public void incrementCounter3() {
try {
l.lock();
counter++;
} finally {
l.unlock();
}
}
private interface IncrementStrategy {
void use(SynchronizationTest t);
}
private static class IncrementingRunnable implements Runnable {
SynchronizationTest synchronizationTest;
IncrementStrategy methodToUse;
public IncrementingRunnable(SynchronizationTest synchronizationTest, IncrementStrategy methodToUse) {
this.synchronizationTest = synchronizationTest;
this.methodToUse = methodToUse;
}
#Override
public void run() {
for (int i = 0; i < N_Loops; i++) {
methodToUse.use(synchronizationTest);
}
}
}
public void test(IncrementStrategy methodToUse, String methodName) {
counter = 0;
Thread[] threads = new Thread[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
threads[i] = new Thread(new IncrementingRunnable(this, methodToUse));
threads[i].start();
}
for (int i = 0; i < N_THREADS; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(methodName + " diff than expected " + (counter - N_THREADS * N_Loops));
}
public void test() {
test(t -> t.incrementCounter0(), "incrementCounter0 (expected to be wrong)");
test(t -> t.incrementCounter1(), "incrementCounter1");
test(t -> t.incrementCounter2(), "incrementCounter2");
test(t -> t.incrementCounter3(), "incrementCounter3");
}
public static void main(String[] args) {
new SynchronizationTest().test();
}
}
I know, that ExecutorService should be used, whole problem can be solved with AtomicLong, but it is not the point of this question.
Output of the code is:
incrementCounter0 (expected to be wrong) diff than expected -1831489
incrementCounter1 diff than expected 0
incrementCounter2 diff than expected -599314
incrementCounter3 diff than expected 0
PS.
If I add the field to SynchronizationTest
Object counterLock = new Object();
and change
incrementCounter2 to:
public void incrementCounter2() {
synchronized (counterLock) {
counter++;
}
}
Then incremetCounter2 works as expected.
You're synchronizing on different objects
incrementCounter1 synchronizes on this, while incrementCounter2 synchronizes on the counter Integer object itself.
You are trying to use two lock monitors (assuming counter is an Object, perhaps Integer?)
public class Foo {
// Uses instance of Foo ("this")
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
// uses counter object as lock monitor
synchronized (counter) {
counter++;
}
}
}
I am not sure what you are trying to achieve with counter++ as it seems counter is of type Integer?
Few options to fix your problem:
Use a the same lock monitor
You might want to look into AtomicInteger
Use the lock API (e.g., ReentrantReadWriteLock)
Hideous.
synchronized void method(...
Synchronizes on the this Object.
synchronized(object) {
...
Synchronizes on object.
Now:
synchronized (counter) {
++counter;
must also synchronize on an Object, but counter is a primitive type, an int.
What happens, is that counter is boxed in an Integer.
When counter is 0 .. 127 the Integer object retrieved is everytime different, but shared. For say 1234 a new unique Integer object is created, and synchronized has no effect whatsoever. (Integer being immutable.)
I would call this almost a language error, something for FindBugs to find.

Refering a value in a class which is in same pacakage

I have two classes, main and timex. I want to display the value of a variable in my timex class, but I always get the answer 0.
public class mainaxe {
public static void main (String arg[]) {
timex n = new timex();
int n2 = timex.a;
n.timedel();
for(int i=0; i<20; i++) {
System.out.println("the time is :" + n2);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}
}
}
And this is my timex class:
public class timex extends Thread{
public static int a;
public int timedel(){
for(int i=0; i<200; i++) {
try {
Thread.sleep(1000);
a = a + 5;
}
catch (InterruptedException e){}
// start();
}
return a;
}
}
I want to get the value from the timex class and use it in my main class to print the value for every 1 sec.
I guess you need something like,
Mainaxe.java
package mainaxe;
public class Mainaxe {
public static void main(String arg[]) {
Timex n = new Timex();
n.start();
// int n2 = Timex.a;
// n.timedel();
for (int i = 0; i < 20; i++) {
System.out.println("the time is :" + Timex.a);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
Timex.java
package mainaxe;
public class Timex extends Thread {
public static int a;
public Timex() {
super();
}
#Override
public void run() {
timedel();
}
public int timedel() {
for (int i = 0; i < 200; i++) {
try {
Thread.sleep(1000);
a = a + 5;
} catch (InterruptedException e) {
}
// start();
}
return a;
}
}
If you want a multi-threaded program, then in your class that extends Thread, declare a method exactly like this:
#Override
public void run () {
// in here, put the code your other thread will run
}
Now, after you create a new object of this class:
timex n = new timex();
you have to start the thread like this:
n.start();
This causes the object to start running its run method in a new thread. Having your main thread call other methods in n won't do anything with the new thread; any other method called by the main thread will be performed in the main thread. So you can't communicate with the new thread with a function call. You have to do it with other means, such as you were trying to do with your variable a.

Java Multi threading

I have to use two threads such that one thread prints all the odd numbers less than 10, and the other to print even numbers less than 10 and the final output should be in sequence.
I have achieved this as follows. I want to do the same using synchronized methods? How to do it?
class printodd extends Thread{
public void run() {
super.run();
for(int i=0;i<10;i=i+2){
System.out.println("even "+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class printeven extends Thread{
public void run() {
super.run();
for(int i=1;i<10;i=i+2)
{
System.out.println("odd "+i);
try {
Thread.sleep(1050);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class PrintNumSeq{
public static void main(String[] args) {
printodd p=new printodd();
printeven e=new printeven();
e.start();
p.start();
}
}
Try this
public class PrintNumSeq extends Thread {
static Object lock = new Object();
static int n;
int even;
PrintNumSeq(int r) {
this.even = r;
}
public void run() {
try {
synchronized (lock) {
for (;;) {
while ((n & 1) != even) {
lock.wait();
}
n++;
lock.notify();
if (n > 10) {
break;
}
System.out.println(n);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new PrintNumSeq(1).start();
new PrintNumSeq(0).start();
}
}
output
1
2
3
4
5
6
7
8
9
10
public class SequentialThreadPrinter {
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(0);
EvenThread even = new EvenThread("even", counter);
OddThread odd = new OddThread("odd", counter);
even.start();
odd.start();
}
}
private static class EvenThread extends Thread {
private String name;
private AtomicInteger counter;
public EvenThread(String name, AtomicInteger counter) {
this.name = name;
this.counter = counter;
}
public void run() {
do {
synchronized (counter) {
if (counter.get() % 2 == 0) {
System.out.println("Thread is " + name + ", Counter is = " + counter.getAndAdd(1));
counter.notifyAll();
} else {
try {
counter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} while (counter.get() <= 10);
}
}
private static class OddThread extends Thread {
private String name;
private AtomicInteger counter;
public OddThread(String name, AtomicInteger counter) {
this.name = name;
this.counter = counter;
}
public void run() {
do {
synchronized (counter) {
if (counter.get() % 2 != 0) {
System.out.println("Thread is " + name + ", Counter is = " + counter.getAndAdd(1));
counter.notifyAll();
} else {
try {
counter.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} while (counter.get() <= 10);
}
}
}
Hi in here you have to use java synchronization. Basically synchronization is Java mechanism shared between thread which will block all other threads while one is running. By doing so in your case you can print them sequentially.
You can read the following tutorial to understand it
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Be careful though while you use it, because not using carefully might create a deadlock
http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
You could achieve this by having the threads acquire a common lock in order to be allowed to print anything.
The "lock" could be some singleton like:
public class Lock {
private static Lock instance;
private static boolean inUse = false;
public static Lock getInstance() {
if(instance == null) {
instance = new Lock();
}
return instance;
}
public boolean acquireLock() {
boolean rv = false;
if(inUse == false) {
inUse = true;
rv = true;
}
return rv;
}
public void releaseLock() {
inUse = false;
}
}
Whenever a thread wants to print it has to call acquireLock() and if it returns true, then it can print. If it returns false, then it has to wait until it returns true. Immediately after printing the thread calls releaseLock() so that the Lock is freed.
I didn't test this code, so use it at your own risk. I just typed it up really quick as it was the idea I was thinking of.
You can read more about locks and their use in synchronization here: http://en.wikipedia.org/wiki/Lock_(computer_science)

Categories

Resources