Below code I have written for a deadlock, but for small "for loop" code is not falling in deadlock while when I keep "for loop" till 10 then deadlock is occurring.
Can someone plz explain, why it is showing such behavior ?
public class CustomerUpdateDeadloackThread {
public static void main(String[] args) {
Customer cstmr = new Customer("Peter");
Address adrs = new Address("B-232, Bangalore");
// For loop till 3 is not showing deadlock.
for (int i=0; i<10;i++){
new Thread(new TagObjectsToEachOther(cstmr, adrs)).start();
new Thread(new TagObjectsToEachOther(adrs, cstmr)).start();
}
}
}
interface CustomerUpdater {
public boolean update(Object obj);
}
class TagObjectsToEachOther implements Runnable {
CustomerUpdater taskItem;
Object objToUpdateWith;
public TagObjectsToEachOther(CustomerUpdater cspdtr, Object obj2) {
this.taskItem = cspdtr;
this.objToUpdateWith = obj2;
}
#Override
public void run() {
taskItem.update(objToUpdateWith);
System.out.println(" Task done :" + Thread.currentThread().getName());
}
}
class Address implements CustomerUpdater {
String address;
Customer customer;
public Address(String addrs) {
this.address = addrs;
}
#Override
public boolean update(Object cstmr) {
synchronized (this) {
synchronized ((Customer) cstmr) {
try {
this.customer = (Customer) cstmr;
Thread.sleep(2000); // or else do some other work here
} catch (CustomerUpdateFailureException e) {
e.getCause();
return false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}
}
class Customer implements CustomerUpdater {
String name;
Address address;
public Customer(String nm) {
this.name = nm;
}
#Override
public boolean update(Object adrs) {
synchronized (this) {
synchronized ((Address) adrs) {
try {
this.address = (Address) adrs;
Thread.sleep(2000); // or else do some other work here
} catch (CustomerUpdateFailureException e) {
e.getCause();
return false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}
}
class CustomerUpdateFailureException extends RuntimeException {
private static final long serialVersionUID = 1L;
#Override
public String getMessage() {
return "Uncompitable update";
}
}
You're only going to get a deadlock if one of your threads obtains one monitor and the other thread obtains the other monitor before the first thread obtains the second monitor. The more threads you have obtaining the monitors on the two objects, the more likely it is that one of them will obtain just one lock and be pre-empted before it gets a chance to obtain the second monitor.
In other words, this is fine, and just causes a wait:
Thread A Thread B
Lock X
Lock Y
Lock Y // Blocks (temporary)
Sleep
Lock X
Sleep
Whereas this causes deadlock:
Thread A Thread B
Lock X
Lock Y
Lock Y // Blocks (deadlock)
Lock X // Blocks (deadlock)
If you move your Thread.sleep(2000) call to between your two synchronized statements (in both methods) then you're almost guaranteed to get a deadlock, without any looping at the top level.
Related
I'm synchronizing and blocking on the same object. Each thread calls the testQueue() method in the PuppetShow class which instantiates a distinct object for each thread to block on. My problem is that once capacity==0, the first thread to encounter that condition calls wait() on its object and then the program hangs and no other thread runs. The third thread outputs "waaah" per the println statement and then no other lines are executed, despite the fact that I instantiate threads after this one.
How do I move past the lock.wait() line in the testQueue method in the PuppetShow() class?
I want to be able to block on distinct objects and add them to vectors in order to queue groups of threads. That's why I'm blocking on distinct objects and then adding these to a vector. To notify the thread I simply notify the element at a position in the vector.
import java.util.Vector;
public class PuppetShow {
private int numSeats = 2;
private int capacity = numSeats;
private Vector<Object> attendingPuppetShow = new Vector<Object>();
public Vector<Object> waitingStudents = new Vector<Object>();
public void testQueue() {
Object lock = new Object();
System.out.println("testQueue begin");
synchronized(lock) {
if(testAttending(lock)) {
try {
System.out.println("waaah");
lock.wait();
System.out.println("ugh");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public synchronized boolean testAttending(Object lock) {
System.out.println("testAttending");
boolean status;
if(capacity==0) {
waitingStudents.add(lock);
System.out.println("capacity="+capacity+" ws size="+waitingStudents.size());
status = true;
}
else {
capacity--;
attendingPuppetShow.add(lock);
System.out.println("capacity="+capacity+" aPS size="+attendingPuppetShow.size());
status = false;
}
return status;
}
public synchronized void testRelease() {
if(waitingStudents.size() > 0) {
while(waitingStudents.size() > 0) {
synchronized(waitingStudents.elementAt(0)) {
waitingStudents.elementAt(0).notify();
}
waitingStudents.removeElementAt(0);
capacity++;
}
}
}
}
class GreenStudent extends Thread {
private PuppetShow ps = new PuppetShow();
public GreenStudent(int id, PuppetShow ps) {
setName("GreenStudent-" + id);
this.ps = ps;
}
#Override
public void run() {
System.out.println(getName()+" queuing for show");
ps.testQueue();
}
}
class StaffMember extends Thread {
private PuppetShow ps = new PuppetShow();
public StaffMember(int id, PuppetShow ps) {
setName("StaffMember-" + id);
this.ps = ps;
}
#Override
public void run() {
ps.testRelease();
}
}
class Driver {
public static void main(String[] args) {
// TODO Auto-generated method stub
PuppetShow ps = new PuppetShow();
GreenStudent gs1 = new GreenStudent(1, ps);
GreenStudent gs2 = new GreenStudent(2, ps);
GreenStudent gs3 = new GreenStudent(3, ps);
StaffMember sm = new StaffMember(1,ps);
gs1.run();
gs2.run();
gs3.run();
sm.run();
}
}
gs1.run();
gs2.run();
gs3.run();
sm.run();
Needs to be
gs1.start();
gs2.start();
gs3.start();
sm.start();
In your example, run will be invoked by the calling thread (main thread). start will launch another thread then eventually call run.
I have an object A on which I'm updating some data every second and other objects B and C which want to use the data only once per update.
Every object work in parallel.
How can I make B and C wait for the update in A ?
I've seen some similar questions but their responses didn't help me.
I've seen that I could use a "synchronized" bloc on an object D, but they just put the bloc without telling how to instanciate or share that object.
The following code is what I use for my tests. I managed to get them working in parallel but I'm stuck with the suspending part.
This is the class for A
public class Master{
public static void main(String[] args) throws Exception {
Worker B = new Worker("B");
B.start();
Worker C = new Worker("C");
C.start();
while(true)
{
Thread.sleep(1000);
// update data
// notify every thread waiting that they can resume
}
}
}
This is the class used for B and C
public class Worker extends Thread
{
Worker(String name)
{
super("Worker " + name);
}
public void run()
{
int i = 0;
while(!this.isInterrupted())
{
// wait for A to update data
System.out.println(i);
i++;
}
System.out.println("thread interrupted");
}
}
From there, what do I need to add for the purpose I'm looking for ?
To do it very low level, only using the lang APIs, you should use wait/notifyAll.
Not that I used Main.class as an arbitrary object to synchronize
public class Main {
public static void main(String[] args) {
SharedData sharedData = new SharedData();
Worker w1 = new Worker("Worker 1", sharedData);
Worker w2 = new Worker("Worker 2", sharedData);
w1.start();
w2.start();
while (true) {
try {
Thread.sleep(1000);
sharedData.increase();;
System.out.println("Master: " + sharedData.value());
synchronized (Main.class) {
Main.class.notifyAll();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class SharedData {
private int data = 0;
public void increase () {
data++;
}
public int value() {
return data;
}
}
class Worker extends Thread {
private String workerName;
private SharedData sharedData;
public Worker(String workerName, SharedData sharedData) {
super();
this.workerName = workerName;
this.sharedData = sharedData;
}
#Override
public void run() {
while (true) {
try {
synchronized (Main.class) {
Main.class.wait();
}
System.out.println(workerName + ": " + sharedData.value());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Not sure if I understand you correctly, but this might be worth checking out for you:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
Why use threads at all? Why not just do this?
public class Master {
public static void main(String[] args) {
Worker B = new Worker("B");
Worker C = new Worker("C");
while(true) {
Thread.sleep(1000);
updateData();
B.doWork();
C.doWork();
}
}
}
public class Worker
{
public void doWork() {
System.out.println(i);
i++;
}
private int i = 0;
}
I'm trying to make a parking lot program. I've got multiple threads that put car objects into a queue, then into a shared buffer. Once the sharedBuffer reaches the maximum of 50 elements.
Here is the problem: Once the shared Buffer reaches the maximum amount of elements. I want the thread to start queuing up elements to the queue. Instead the thread waits for the semaphore to open a spot.
public class Buffer {
private LinkedList queue = new LinkedList();
private Semaphore spots = new Semaphore(50);
public synchronized void put(String car) {
try {
spots.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
queue.addLast(car);
notifyAll();
}
public synchronized String get() throws InterruptedException {
String t = (String) queue.removeFirst();
spots.release();
notifyAll();
return t;
}
public int getSize() {
return queue.size();
}
}
Method in my Queue class that either adds the car to the buffer or adds it straight to the queue if the buffer is full.
public void addToQueue(int queue) {
if (queue == 1 && northQueue<20) {
if(buffer.getSize()==50){
northQueue++;
}else{
buffer.put("Volvo");
}
}
}
public void run() {
while (true) {
// System.out.println("Thread: " + threadNumber);
eq.addToQueue(threadNumber);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
I am trying to do it using two threads like below. Can someone point the obvious mistake I am doing here?
public class OddEven {
public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();
static Thread threadEven = new Thread() {
#Override
public void run() {
printEven();
}
public synchronized void printEven() {
while (!available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = false;
notifyAll();
}
};
static Thread threadOdd = new Thread() {
#Override
public void run() {
printOdd();
}
public synchronized void printOdd () {
while (available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = true;
notifyAll();
}
};
public static void main(String[] args) {
int n = 20;
for (int i = 1; i < n; i++) {
queue.add(i);
}
threadOdd.start();
threadEven.start();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
threadOdd.join();
threadEven.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
But this program is only printing 1 and quitting. After printing 1 the available should be true and printEven should wake up, print and set available to false. I don't understand what is going wrong here? I saw other solutions but want to know why my solution is not working.
Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for
public void printOdd() {
synchronized(this) {
...
}
}
where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.
hello guys this is my code , problem am facing is that despite calling notifyAll, it is not releasing the lock , can you please state the reason and tell the solution. Am new to threads. Thanks in advance.
class Lock1 {}
class Home1 implements Runnable {
private static int i = 0;
private Lock1 object;
private Thread th;
public Home1(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 1");
}
}
}
class Home2 implements Runnable {
private static int i = 0;
private Lock1 object;
Thread th;
public Home2(Lock1 ob, String t) {
object = ob;
th = new Thread(this);
th.start();
}
public void run() {
synchronized (object) {
while (i != 10) {
++i;
System.out.println(i);
}
try {
// System.out.println("here");
object.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("here thread 2");
}
}
}
public class Locking {
public static void main(String arg[]) {
Lock1 ob = new Lock1();
new Home1(ob, "thread 1");
new Home2(ob, "thread 2");
synchronized (ob) {
ob.notifyAll();
}
}
}
When you use notifyAll, you should also have a state changed and when you use wait, you should check that state change.
In your case it is likely that notifyAll will be called long before the threads really have time to start. (For a computer, starting a thread takes an eternity, like 10,000,000 clock cycles) This means the notifyAll is lost. (It only notifies threads which are actually waiting right at that moment)