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)
Related
ProdCom.java (driver class)
import static java.lang.System.out;
public class ProdCom{
static int full = 50;
static int mutx = 0;
static int empty = 0;
static int currentSize = 0;
public static void acquire(){
while (mutx == 1);
mutx++;
}
public static void release(){
mutx--;
}
public static void main(String args[]){
Thread t = new Thread(new Producerr());
Thread t1 = new Thread(new Consumerr());
t.start();
t1.start();
}
}
Producerr.java
class Producerr implements Runnable{
public void wwait(){
while (ProdCom.currentSize >= ProdCom.full){
}
} public void signal(){
ProdCom.currentSize++;
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
out.println("Num elements" + ProdCom.currentSize);
out.println("producing!");
ProdCom.release();
this.signal();
} while (true);
}
}
Consumerr.java
class Consumerr implements Runnable{
public void wwait(){
while (ProdCom.currentSize <= 0){
out.println("inside consumer wait: ");
out.println("number of elements: " + ProdCom.currentSize);
}
} public void signal(){
ProdCom.currentSize--;
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
out.println("Num elements" + ProdCom.currentSize);
out.println("Consuming!");
ProdCom.release();
this.signal();
} while (true);
}
}
Above is my solution to the consumer-producer problem. The driver class ProdCom has variables full, empty and mutx for controlling producer t and consumer t1's access to the variable currentSize (Thus simulating the current number of items in a buffer). But when I run the code, the output seems to indicate t1 and t aren't taking turns to change currentSize, instead one of them repeats forever and gets stuck...I'm wondering why? Thanks.
I've improved your code a bit, and you'll notice that many of the concepts mentioned by Joni are considered.
ProdCom.java
import java.lang.*;
public class ProdCom{
static final int FULL = 50;
static final int EMPTY = 0;
static volatile int mutx = 0;
static volatile int currentSize = 0;
static Object lockObject = new Object();
public static void acquire(){
/* since mutx is defined volatile, the spinlock works,
but you reconsider this approach. There are cheaper
methods of heating the room */
while (mutx == 1);
mutx++;
}
public static boolean isEmpty() {
synchronized(lockObject) {
if (currentSize <= EMPTY) return true;
return false;
}
}
public static boolean isFull() {
synchronized(lockObject) {
if (currentSize >= FULL) return true;
return false;
}
}
public static int getCurrentSize() {
synchronized(lockObject) {
return currentSize;
}
}
public static void release(){
mutx--;
}
public static void incCurrentSize()
{
synchronized(lockObject) {
currentSize++;
}
}
public static void decCurrentSize()
{
synchronized(lockObject) {
currentSize--;
}
}
public static void main(String args[]){
Thread t = new Thread(new Producerr());
Thread t1 = new Thread(new Consumerr());
t.start();
t1.start();
}
}
Consumerr.java
import java.lang.*;
class Consumerr implements Runnable {
public void wwait() {
while (ProdCom.isEmpty()){
System.out.println("inside consumer wait: ");
System.out.println("number of elements: " + ProdCom.getCurrentSize());
try {
/* we don't spinlock here */
Thread.sleep(50);
} catch (Exception e) {
/* do nothing */
}
}
}
public void signal(){
ProdCom.decCurrentSize();
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
System.out.println("Num elements " + ProdCom.getCurrentSize());
System.out.println("Consuming!");
this.signal();
ProdCom.release();
} while (true);
}
}
Producerr.java
import java.lang.*;
class Producerr implements Runnable {
public void wwait(){
while (ProdCom.isFull()){
try {
Thread.sleep(50);
} catch(Exception e) { /* do nothing */ }
}
}
public void signal(){
ProdCom.incCurrentSize();
}
public void run(){
do {
this.wwait();
ProdCom.acquire();
System.out.println("Num elements : " + ProdCom.getCurrentSize());
System.out.println("producing!");
this.signal();
ProdCom.release();
} while (true);
}
}
The Java memory models allows threads to cache the values of variables, and different threads to have different caches. This means that the spin lock in acquire easily becomes an infinite loop: the thread in acquire may use the cached value mutx = 1 and never read the updated value from main memory:
while (mutx == 1); // infinite loop even if another thread changes mutx
Another problem is that the ++ and -- operators are not atomic: they read the value of the variable, modify it, and write it back. If two threads run currentSize++ and currentSize-- at the same time it is possible one of them is lost.
You can fix these problems by using an AtomicInteger object and its methods instead of int, for example in ProdCom:
static AtomicInteger currentSize = new AtomicInteger(0);
static AtomicInteger mutx = new AtomicInteger(0);
public static void acquire() {
while (!mutx.compareAndSet(0, 1));
}
public static void release() {
mutx.set(0);
}
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.
I have a program where 3 Threads are trying to print numbers in sequence from 1 to 10. I am using a CountDownLatch to keep keep a count.
But the program stops just after printing 1.
Note: I am aware that using AtomicInteger instead of Integer can work. But I am looking to find out the issue in the current code.
public class Worker implements Runnable {
private int id;
private volatile Integer count;
private CountDownLatch latch;
public Worker(int id, Integer count, CountDownLatch latch) {
this.id = id;
this.count = count;
this.latch = latch;
}
#Override
public void run() {
while (count <= 10) {
synchronized (latch) {
if (count % 3 == id) {
System.out.println("Thread: " + id + ":" + count);
count++;
latch.countDown();
}
}
}
}
}
Main program:
public class ThreadSequence {
private static CountDownLatch latch = new CountDownLatch(10);
private volatile static Integer count = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Worker(0, count, latch));
Thread t2 = new Thread(new Worker(1, count, latch));
Thread t3 = new Thread(new Worker(2, count, latch));
t1.start();
t2.start();
t3.start();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Edited program with AtomicInteger:
public class ThreadSequence {
private static AtomicInteger atomicInteger = new AtomicInteger(1);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new WorkerThread(0, atomicInteger));
Thread t2 = new Thread(new WorkerThread(1, atomicInteger));
Thread t3 = new Thread(new WorkerThread(2, atomicInteger));
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("Done with main");
}
}
public class WorkerThread implements Runnable {
private int id;
private AtomicInteger atomicInteger;
public WorkerThread(int id, AtomicInteger atomicInteger) {
this.id = id;
this.atomicInteger = atomicInteger;
}
#Override
public void run() {
while (atomicInteger.get() < 10) {
synchronized (atomicInteger) {
if (atomicInteger.get() % 3 == id) {
System.out.println("Thread:" + id + " = " + atomicInteger);
atomicInteger.incrementAndGet();
}
}
}
}
}
But the program stops just after printing 1.
No this is not what happens. None of the threads terminate.
You have a own count field in every worker. Other threads do not write to this field.
Therefore there is only one thread, where if (count % 3 == id) { yields true, which is the one with id = 0. Also this is the only thread that ever modifies the count field and modifying it causes (count % 3 == id) to yield false in subsequent loop iterations, causing an infinite loop in all 3 threads.
Change count to static to fix this.
Edit
In contrast to Integer AtomicInteger is mutable. It is a class that holds a int value that can be modified. Using Integer every modification of the field replaces it's value, but using AtomicInteger you only modify the value inside the AtomicInteger object, but all 3 threads continue using the same AtomicInteger instance.
Your "count" is a different variable for each thread, so changing it in one thread doesn't affect the rest, and so they are all waiting for it to change, without any one that can do it.
Keep the count as static member in Worker class - common for all object in the class.
You can use below code to print sequential numbers using multiple threads -
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadCall extends Thread {
private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
private ThreadCall next;
public void setNext(ThreadCall t) {
this.next = t;
}
public void addElBQ(int a) {
this.bq.add(a);
}
public ThreadCall(String name) {
this.setName(name);
}
#Override
public void run() {
int x = 0;
while(true) {
try {
x = 0;
x = bq.take();
if (x!=0) {
System.out.println(Thread.currentThread().getName() + " =>" + x);
if (x >= 100) System.exit(0); // Need to stop all running threads
next.addElBQ(x+1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int THREAD_COUNT = 10;
List<ThreadCall> listThread = new ArrayList<>();
for (int i=1; i<=THREAD_COUNT; i++) {
listThread.add(new ThreadCall("Thread " + i));
}
for (int i = 0; i < listThread.size(); i++) {
if (i == listThread.size()-1) {
listThread.get(i).setNext(listThread.get(0));
}
else listThread.get(i).setNext(listThread.get(i+1));
}
listThread.get(0).addElBQ(1);
for (int i = 0; i < listThread.size(); i++) {
listThread.get(i).start();
}
}
}
I hope this will resolve your problem
When using synchronized block or method, we synchronized by mutable object. But I don't understand how to use Locks with Conditions from j.u.c.. I'm trying to solve puzzle with two workers and a cart with lock and conditions. When first worker add weight to the cart - second wait. When cart is full, than first worker wait and second releases the cart.
I create two threads for each worker and use one cart. But in reality only one thread performs (worker, that add weight) until cart is full. Than program blocks. What I'm doing wrong and what I misunderstand?
That's my implementation of this puzzle.
package puzzles.workers;
public enum WorkerType {
ADDER, REDUCER;
}
Cart class
package puzzles.workers;
public class Cart {
private static final int INITIAL_CAPACITY = 10;
private static final int INITIAL_WEIGHT = 0;
private int capacity;
private int weight;
public Cart() {
this(INITIAL_CAPACITY);
}
public Cart(int capacity) {
this.capacity = capacity;
weight = INITIAL_WEIGHT;
}
public void addWeight() {
weight++;
}
public void reduceWeight() {
weight--;
}
public int getCapacity() {
return capacity;
}
public int getWeight() {
return weight;
}
}
Worker class.
package puzzles.workers;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class WorkerWithLock implements Runnable {
private final Cart cart;
private WorkerType workerType;
final Lock lock = new ReentrantLock();
final Condition whenEmpty = lock.newCondition();
final Condition whenFull = lock.newCondition();
public WorkerWithLock(Cart cart, WorkerType workerType) {
this.cart = cart;
this.workerType = workerType;
}
#Override
public void run() {
while (true) {
if (workerType == WorkerType.ADDER) {
try {
addWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
} else {
try {
reduceWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await();
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await();
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Cart cart = new Cart(5);
WorkerWithLock adder = new WorkerWithLock(cart, WorkerType.ADDER);
WorkerWithLock reducer = new WorkerWithLock(cart, WorkerType.REDUCER);
new Thread(reducer).start();
new Thread(adder).start();
}
}
It is a kind of a race condition
That is because both threads are waiting.
One in addWeightand one in reduceWeight.
First the reducer stops, if weight is 0. At this time, the adder is may be not already started.
Than the adder stops, if weight = cpacity - 1
Now, both are waiting for an interrupt().
EDIT1. See my comments in the code
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await(); //<-- ADDER waits here
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await(); //<-- REDUCER waits here
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
EDIT2: Ok, now I understand the behaviour.
Your code is designed to synchronize ONE object for multiple threads, but your are using TWO objects.
Every of your both WorkerWithLock Objects has its own Lock and Condition objects. So calls of lock.lock() and whenFull.signalAll() in object ADDER does not effect Object REDUCER.
Your code will work if you make the lock and condition variables static, so that both objects are working with the same lock and the same condition
final static Lock lock = new ReentrantLock();
final static Condition whenEmpty = lock.newCondition();
final static Condition whenFull = lock.newCondition();
Sometimes multithreading is hard :)
I encountered a problem:Will inner class method cannot synchronized the object in outer class? A answer from stackoverflow told me : No. But I really want to know the reason.
For example:
I designed a thread pool with at most 5 threads to do work.
public class ThreadPool{
// Ignore the Task class
private LinkedList<Task> tasks;
Executor[] executors = new Executor[5];
private static ThreadPool pool = null;
private ThreadPool() {
tasks = new LinkedList<Task>();
for (int i = 0; i < 5; i++) {
executors[i] = new Executor(i);
}
}
public static ThreadPool getInstance() {
if (pool == null) {
pool = new ThreadPool();
}
return pool;
}
public void addTask(Task task) {
/** igore code here*/
}
private class Executor extends Thread {
private int i;
public Executor(int i) {
this.i = i;
start();
}
public void run() {
Task task = null;
synchronized (tasks) {
if (tasks.size() == 0) {
System.out.println("tasks's size is : " + tasks.size());
try {
while (tasks.size() == 0) {
tasks.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (tasks.size() > 0)
task = tasks.removeFirst();
}
if (task != null) {
/** ignore code here */
}
}
}
}
Unfortunately, the synchronized doesn't work. But when I put the synchronized block into
synchronized (ThreadPool.this) {
...
}
it works.
So, i want to know why inner class method cannot synchronized the object in outer class.
Hope for a detailed answer.