I have a two part question...
I have a class with a function in it that can only be accessed by any one thread at a given time. Making this a synchronized function or a synchronized block still allows for multiple threads since different threads are accessing it within the class. How can I make sure only one thread accesses this code? (See code example below)
With the synchronized function, the calls to the function are queued up. Is there any way to only allow the last call to the function to access the code? So if I have Thread1 currently accessing my function, then Thread2 and Thread3 try to access it (in that order) only Thread3 will be given access once Thread1 is complete.
public void doATask() {
// I create a new thread so the interface is not blocked
new Thread(new Runnable() {
#Override
public void run() {
doBackgroundTask();
}
}).start();
}
private void doBackgroundTask(MyObject obj) {
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
}
Thanks for any help!
If the second thread in your example can just return, you could use a combination of a lock and keeping track of the last thread executing the method. It could look like this:
private volatile Thread lastThread;
private final ReentrantLock lock = new ReentrantLock();
private void doBackgroundTask(Object obj) throws InterruptedException {
Thread currentThread = Thread.currentThread();
lastThread = currentThread;
try {
// wait until lock available
lock.lockInterruptibly();
// if a thread has arrived in the meantime, exit and release the lock
if (lastThread != currentThread) return;
// otherwise
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
} finally {
lock.unlock();
}
}
Full working test with additional logging that shows the thread interleaving and that T2 exits without doing nothing:
class Test {
private volatile Thread lastThread;
private final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws Exception {
final Test instance = new Test();
Runnable r = new Runnable() {
#Override
public void run() {
try {
instance.doBackgroundTask(null);
} catch (InterruptedException ignore) {}
}
};
Thread t1 = new Thread(r, "T1");
Thread t2 = new Thread(r, "T2");
Thread t3 = new Thread(r, "T3");
t1.start();
Thread.sleep(100);
t2.start();
Thread.sleep(100);
t3.start();
}
private void doBackgroundTask(Object obj) throws InterruptedException {
Thread currentThread = Thread.currentThread();
System.out.println("[" + currentThread.getName() + "] entering");
lastThread = currentThread;
try {
// wait until lock available
lock.lockInterruptibly();
// if a thread has arrived in the meantime, exit and release the lock
if (lastThread != currentThread) return;
// otherwise
// perform long task here that is only being run by one thread
// and also only accepts the last queued thread
System.out.println("[" + currentThread.getName() + "] Thinking deeply");
Thread.sleep(1000);
System.out.println("[" + currentThread.getName() + "] I'm done");
} finally {
lock.unlock();
System.out.println("[" + currentThread.getName() + "] exiting");
}
}
}
Output:
[T1] entering
[T1] Thinking deeply
[T2] entering
[T3] entering
[T1] I'm done
[T1] exiting
[T2] exiting
[T3] Thinking deeply
[T3] I'm done
[T3] exiting
What you want is probably a worker thread that waits for a signal to do some work. doATask() simply sends a signal to trigger the work. Accumulative signals are equivalent to one signal.
final Object lock = new Object();
MyObject param = null;
public void doATask(arg)
synchronized(lock)
param=arg;
lock.notify();
MyObject awaitTask()
synchronized(lock)
while(param==null)
lock.wait();
tmp=param;
param=null;
return tmp;
// worker thread
public void run()
while(true)
arg = awaitTask();
doBackgroundTask(arg);
Related
I am writing a program to test how a thread can keep waiting if another thread has acquired lock on same object but after looking at output I am not sure how locking works in java. Here is what i have written:
public class Locking {
synchronized void methodA() {
System.out.println("inside A , " + Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
new Locking().execute();
}
private void execute() throws InterruptedException {
Thread t1 = new Thread(new MyThread());
t1.setName("t1");
Thread t2 = new Thread(new MyThread());
t2.setName("t2");
t1.start();
Thread.sleep(5000);
t2.start();
}
class MyThread implements Runnable {
#Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
methodA();
}
}
}
}
I expected thread t2 to be waiting forever and program will print only
inside A , t1
but when i run the program , I get following output:
inside A , t1
inside A , t2
Can anyone explain what is going on here?
I am writing a program to test how a thread can keep waiting if
another thread has acquired lock on same object
The single lock is here :
synchronized void methodA() {
System.out.println("inside A , " + Thread.currentThread().getName());
}
It takes the locks on the current instance but no statement in your code locks in a way where a thread could wait forever the lock.
Look at my comments :
#Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// the lock is set here
methodA();
// and that is released here
}
}
Make the synchronized method never releases the lock and only one of the thread will be able to enter in :
synchronized void methodA() {
while (true) {
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t1
inside A , t1
...
Her are some other examples to play with threads.
Replace sleep() by wait() and the current thread will release the lock :
synchronized void methodA() {
while (true) {
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
wait();
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t2
Use notify() (to notify a waiting thread) and wait() (to make the current thread wait and release the lock if it has) to make threads collaborating between them :
synchronized void methodA() {
while (true) {
notify();
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
wait();
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t2
inside A , t1
inside A , t2
...
That is intended situation.
Your t1 thread is waiting in another thread not main thread.
In your main thread(make threads and call start()), just waiting 5 seconds and start thread2
your synchronized method is synchronizing only when thread 1 calls that method not forever.
After thread1 calls synchorinized method and return, thread1 is stopping 5seconds.
In that time, thread2 can use that method.
The keyword synchronized infront of a method means, that the method cannot be called by two threads at the same time.
As soon as the method is called by a thread, other threads trying to call that same method are blocked until the first thread returns from that method. Afterwards the other threads calling the same method can automatically continue with the call (one at a time).
You implicit lock with synchronized is working for a short period - that is the println after that the lock is released. Both of your threads are racing to obtain the lock there.
Change your code to this and you will see the behavior you want
class MyThread implements Runnable {
#Override
public void run() {
methodA();
}
}
synchronized void methodA() {
while(true)
System.out.println("inside A , " + Thread.currentThread().getName());
}
This program works fine by printing alternate numbers via different threads but when all the numbers from 0-9 are printed Why does this program not stop? I have to manually stop my application.
public class EvenOddPrinter implements Runnable{
private AtomicInteger num = new AtomicInteger(0);
private Object lock = new Object();
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Executor {
public static void main(String[] args) throws InterruptedException {
EvenOddPrinter eop = new EvenOddPrinter();
Thread t1 = new Thread(eop);
Thread t2 = new Thread(eop);
t1.start();
t2.start();
}
}
that's because in the last Thread getting stuck at wait. notifyAll will notify all waiting thread if any there and release lock.
while (num.get()<10){
// existing implementation
}
lock.notifyAll();
The second thread t2 keeps waiting on the lock in the end, and t1 doesnt do the notify() anymore because the while condition becomes false. You must put a lock.notify(); statement outside of the while loop.
As soon as the number reached 8 the first thread calls notify() and goes to wait(). Second thread then makes the number 9 and calls notify() and goes to wait(). First thread is then not able to go inside the loop as specified in the condition, therefore, it exits the synchronized and block and finishes but second thread is still waiting. There has to be a mechanism to notifyAll() as soon as one of the threads exits the synchronized block which is exactly what I did.
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();
}
Also, lock is pointless when I am using AtomicInteger (or the other way round).
I was trying to create A Java dead lock program . I know in real time we wont be creating any dead lock in thread. Unfortunately I have been asked in one of the interview to writing a "Deadlock program using two threads". So here it is
package Thread.DeadLock;
public class deadLock2 {
static ThreadSample1 t1 = new ThreadSample1();
static ThreadSample2 t2 = new ThreadSample2();
public static void main(String args[]) {
t1.start();
t2.start();
}
public static class ThreadSample1 extends Thread {
public void run() {
System.out.println("In first run method");
try {
System.out.println("Holding lock in first one");
synchronized (t1) {
System.out.println("t1 going to wait for t2");
t1.wait();
System.out.println("t1 finished for waiting");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static class ThreadSample2 extends Thread {
public void run() {
System.out.println("In second run method");
try {
System.out.println("Holding lock for second one");
synchronized (t2) {
System.out.println("t2 going to wait for t1");
t2.wait();
System.out.println("t2 finished for waiting");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I can see the program is getting stuck. I am assuming that it in deadlock situation. t1.start() waits for t2 to finish its task and t2.start() waits for t1 to finish its task. Now while I try to remove the deadlock by notifying the waiting thread using using t1.notify() I get IllegalMonitorStateException.
Can somebody tell in this situation how to remove the deadlock without causing any situation.
First, this is not deadlock. As you correctly described, deadlock is usually situation when there is circular dependency between two or more threads waiting for resources that is held by other thread.
Here, each thread independently waits for notification on itself which is actually not delivered by anybody else in the system. Even if there is no deadlock.
Secondly, IllegalMonitorStateException means that you try to notify/wait on monitor which is not held by the thread. In other words, there is no synchronized prior to notify/wait.
Third, to achieve real deadlock you can do something like this:
synchronized(t1) {
synchronized(t2) {
t2.wait();
}
t1.notify();
}
and vice versa for the other thread.
You can not call notify()/notifyAll() unless the current thread owns that object's monitor. To do that, you must synchronize on it, as you did with wait()
The Javadocs for wait() mention this:
This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
Throws:
IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.
And from notify():
A thread becomes the owner of the object's monitor in one of three
ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
See this answer:
Java Wait and Notify: IllegalMonitorStateException
package pck.pramod.geekforgeeks;
public class ThreadDeadlock {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
System.out.println(Lock1.toString() + " " + Lock2.toString());
ThreadDemo1 T1 = new ThreadDemo1(Lock1, Lock2, "T1");
ThreadDemo1 T2 = new ThreadDemo1(Lock2, Lock1, "T2");
T1.start();
T2.start();
}
}
class ThreadDemo1 extends Thread {
Object lock1;
Object lock2;
String name;
public ThreadDemo1(Object lock1, Object lock2, String name) {
this.lock1 = lock1;
this.lock2 = lock2;
this.name = name;
}
public void run() {
synchronized (lock1) {
System.out.println(name + " Holding lock ..." + lock1.toString());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println(name + " Waiting for lock ..." + lock2.toString());
synchronized (lock2) {
System.out.println(name + " Holding lock ..." + lock1.toString() + " " + lock2.toString());
}
}
}
}
I have the following kind of code:
synchronized block1 {
//only one thread in the block
}
{lot of code where synchronization not necessary}
synchronized block2 {
//only one thread in the block.
//All the threads that executed block1 before this thread should have already executed this block.
}
Each thread first executes block1, non synchronized block, and block2 in that same order.
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
Is there a way to achieve this in java?
As I understand Critical Section #2 MUST be executed in the same order as Critical Section #1
If thread T1 executes block1 before thread T2, then T1 should execute block2 before T2. There are more than two threads.
Then a Queue might be used to ensure the order of execution.
private Object lock = new Object();
private Queue<Thread> threadQueue = new ArrayDeque<>();
// https://stackoverflow.com/questions/32353283/synchronization-threads-execute-two-critical-sections-in-same-order
public void executeCriticalSectionsInOrder() throws InterruptedException {
// Critical Section #1
synchronized (lock){
// synchronized code #1
// Add self to queue
threadQueue.add(Thread.currentThread());
}
// {lot of code where synchronization not necessary}
// Critical Section #2
synchronized (lock) {
//All the threads that executed block1 before this thread should have already executed this block.
// Wait turn
Thread t = threadQueue.element(); // Do not remove until it is self
while (t != Thread.currentThread()) {
lock.wait();
// After sleep try again
t = threadQueue.element();
}
// Verified own turn. Update status
threadQueue.remove();
// synchronized code #2
lock.notifyAll(); // Awake any waiting thread after exiting section.
}
However If one thread dies/exits without removing itself from the queue, then following threads will be blocked indefinetely. Maybe add a finally block to do the housekeeping?
Note: In Nicholas Robinson's answer a position order was suggested instead of a queue, which seems slightly more efficient.
This basically creates a queue that threads will wait in until their number comes up. [UPDATED]
private AtomicInteger place = new AtomicInteger(0);
private AtomicInteger currentPlaceInQueue = new AtomicInteger(0);
private ReentrantLock lock = new ReentrantLock();
private Condition notNext = lock.newCondition();
public void method() {
ThreadLocal position = new ThreadLocal();
synchronized(this) {
//Your code
position.set(place.getAndIncrement());
}
// More code
lock.lock();
while ((int) currentPlaceInQueue.get() != position.get()) {
notNext.await();
}
// More code
lock.unlock();
currentPlaceInQueue.getAndIncrement();
notNext.notifyAll();
}
The synchronized blocks in your example are a red herring. Your problem is, you have N threads, and you have two blocks of code, and you want to make sure that none of the threads enters the second block until all of them have finished the first block.
You use a CyclicBarrier for that. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
You should be able to use a Lock which you take before calling block1 and release after calling block2.
static Lock lock = new ReentrantLock();
Random random = new Random();
public void block1() throws InterruptedException {
System.out.println("Enter block 1");
Thread.sleep(random.nextInt(500));
System.out.println("Leave block 1");
}
public void block2() throws InterruptedException {
System.out.println("Enter block 2");
Thread.sleep(random.nextInt(500));
System.out.println("Leave block 2");
}
private class BlockTester implements Runnable {
long start = System.currentTimeMillis();
#Override
public void run() {
while (System.currentTimeMillis() < start + 10000) {
lock.lock();
try {
System.out.println("Thread: " + Thread.currentThread().getName());
block1();
block2();
} catch (InterruptedException ex) {
System.out.println("Interrupted");
} finally {
lock.unlock();
}
}
}
}
public void test() throws InterruptedException {
Thread[] blockTesters = {
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester()),
new Thread(new BlockTester())
};
for (Thread t : blockTesters) {
t.start();
}
for (Thread t : blockTesters) {
t.join();
}
}
Am I not using synchronization properly:
In following code i am having 2 problems :
1. while makingmethods (designBusiness,createBusiness,sellBusiness) as synchronized like in this case, a call to wait() says IllegalMonitorStateException but i can not understand why? because in designBusiness method Designer Thread do get a lock so it is supposed to wait on wait call. I am getting IllegalMonitorStateException on wait() and notify() both.
2.Even though when i remove synchronized keyword and use synchronized(this) block for particularly wait() and notify() still i got DEADLOCK! WHY?
public class Main {
HashMap<String, Integer> map = new shop().orderBook();
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.sellBusiness();
Thread.sleep(3000);
main.designBusiness();
Thread.sleep(3000);
main.createBusiness();
}
private synchronized void designBusiness() throws InterruptedException {
Thread designThread = new Thread(new Runnable() {
public void run() {
Set set = map.keySet();
System.out.println("Tracking OrderList");
System.out.println(set.size());
try {
System.out.println("waiting.........");
wait();
System.out.println("wait completed");
System.out.println("after design process items in orderList are "
+ map.keySet().size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Designer Thread");
designThread.start();
System.out
.println("status of Designer Thread" + designThread.isAlive());
}
private synchronized void createBusiness() throws InterruptedException {
Thread createThread = new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()
+ " started");
Creator creator = new Creator();
creator.create(map);
notifyAll();
System.out.println("notified");
}
}, "Creator Thread");
createThread.start();
createThread.join();
System.out.println("status of Creator Thread" + createThread.isAlive());
}
private void sellBusiness() throws InterruptedException {
Thread sellThread = new Thread(new Runnable() {
public void run() {
Seller seller = new Seller();
seller.sellGold(45000, 15);
seller.sellSilver(14000, 60);
seller.noteOrder("Mrs Johnson", 15000, map);
seller.noteOrder("Mr. Sharma", 10000, map);
seller.sellGold(60000, 20);
seller.noteOrder("Mr. Hooda", 17500, map);
System.out.println(Thread.currentThread().getName()
+ " done selling");
}
}, "Seller Thread");
sellThread.start();
sellThread.join();
System.out.println("status of seller Thread" + sellThread.isAlive());
}
}
please help i could not find any solution for this problem and i am searching from last night.
If you got this exception you are not in a block or method that is synchronised on the object you are waiting on. That is the meaning of the exception. The only meaning.
The wait() method you are calling is executed on the instance of the anonymous inner class you are creating. The synchronised method you are creating it from is synchronised on a different object, and it has probably also already executed by the time the inner object gets to the wait() call.
You need to sort out which object is which here. Probably you need to call Main.this.wait(), but it depends on what you think you're trying to do, which isn't clear from your question.
NB you aren't getting a deadlock, you are getting an infinite block. It isn't the same thing.
wait(), notify() and notifyAll() must be used with synchronized. What I would do is trying to solve the deadlock.
To illustrate why you got deadlock (unrelated code removed) (if I guessed right):
public class Main {
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.createBusiness();
}
private synchronized void createBusiness() throws InterruptedException {
// ^^^^^^^^^^^^ got lock
Thread createThread = new Thread(new Runnable() {
public void run() {
synchronized (Main.this) {
// ^^^^^^^^^^^^^^^^^^^^^^^^ try to get lock --> DEADLOCK
Main.this.notifyAll();
}
}
});
createThread.start();
createThread.join();
// ^^^^^^^^^^^^^^^^^^^ wait for createThread to die --> DEADLOCK
}
}
Main thread got the lock of Main.this.
createThread tried to get lock of Main.this, but it's locked by Main.this, hence waiting.
Main thread waited for createThread to die, hence waiting. (2 and 3 can be swapped)
Since I'm not sure what you tried to achieve, I'm not sure if the following is the right solution, but you can try (even if the above guessed wrong):
First, create a lock object.
public class Test {
private Object lock = new Object();
Second, in designer thread
synchronized (lock) {
lock.wait();
}
Third, in creator thread
synchronized (lock) {
lock.notifyAll();
}
wait() must be executed from synchronized block on the same monitor. Since wait() is the same as this.wait() you have to wrap it with synchronized(this):
synchronized(this) {
wait();
}
If you try to unlock an onject by a threas which is not locked by that thread then you may end up with the same error.