Synchronized hashmap access - java

On my computer, using java 8, the following program won't stop even if map access is synchronized. Aren't those synchronized blocks enougth?
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null)
i++;
}
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
}

This will run forever. The while loop in the synchronized block is effectively infinite since it is entered first - thus prohibiting the second synchronized block from ever being entered.

Yes that is expected, your backgroundThread is holding the lock before your main thread and it wont release it until the main thread writes "stop" to the map, the main thread needs the lock to write it the "stop" so basically this is a dead lock.
There are several ways to solve this deadlock, my guess is what you are trying to do is to see how many times you count before the main thread writes "stop" entry in your map.
You can simply acquire and release your lock on each iteration of the loop which makes sense for your scenario.
while (stopRequested.get("stop") == null)
synchronized (stopRequested) {
i++;
}
Another solution could be using concurrentHashMap, check this link for more details

You have two threads synchronizing on stopRequested. Only one synchronized block is permitted to run at any given time. Since it will almost always be the case that backgroundThread’s synchronized block runs first, it will never exit and thus will never allow any other thread to synchronize on stopRequested.
The wait and notify methods exist precisely to solve this problem:
try {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null) {
stopRequested.wait();
i++;
}
}
System.out.println(i);
} catch (InterruptedException e) {
throw new RuntimeException(i);
}
// ...
synchronized (stopRequested) {
stopRequested.put("stop", "true");
stopRequested.notify();
}
The reason this works is that wait() will temporarily, and atomically, release the synchronized lock, allowing another thread to synchronize on that object.
Note that wait() must be called in a loop which checks the condition being waited for, since wait() can occasionally return even if no other thread called notify(). This “spurious wakeup” is due to the nature of threads on some systems.
A well-behaved thread will place the entire wait-loop in a try/catch block, so the thread will exit when interrupted. An interrupt is a request from some other thread asking your thread to stop what it’s doing and exit cleanly.

Thanks for all the answers. Indeed, this is a deadlock. A working synchronization is
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (stopRequested())
i++;
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
static boolean stopRequested()
{
synchronized (stopRequested) {
return stopRequested.get("stop") == null;
}
}
}

Related

Getting IllegalMonitorStateException while printing arraylist using threads

I am trying to print out the content of arraylist using 2 threads, my main goal is to make threads read arraylist in a synchronized way and print its content. Eventhough I use synchronized block, I still am getting IllegalMonitorStateException. I know this is a basic question but I can not get it working, pardon me.
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q1 {
public static Q1 yeni;
public static void main(String[] args) {
// TODO Auto-generated method stub
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
ExecutorService executorService = Executors.newFixedThreadPool(10);
synchronized (list) {
myThread thread1 = new myThread(list);
myThread thread2 = new myThread(list);
thread1.start();
thread2.start();
}
}
}
And here is myThread class
import java.util.*;
public class myThread extends Thread {
List<String> liste;
public myThread(List<String> liste) {
this.liste = liste;
}
#Override
public void run() {
try {
synchronized (Q1.yeni) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
this.wait(3000);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The reason for the IllegalMonitorStateException is that you are calling wait on an object (this) without holding the monitor for that object. You must either wrap this call with a synchronized (this) block, or call wait on Q1.yeni, which this code already has synchronized.
However, it looks like the use of wait might be mistaken. This method is used to wait on a condition, which is signaled with a call to notify or notifyAll on the same object. Since there is no apparent condition in this code, and no usages of notify or notifyAll, I suspect that what you really want to call is this.sleep(3000), which pauses the thread for three seconds, then resumes it after that duration elapses.
The sleep method does not require ownership of any monitors, and does not release ownership of held monitors, so another thread would not be able to enter the synchronized (Q1.yeni) block while one is currently sleeping. This implies that the first thread to enter that block will run to completion, iterating through the entire list, before the second thread has a chance to begin. It's not totally clear if that's what is intended here.
See the documentation for Object.wait and Thread.sleep for more usage information.
A second problem is that Q1.yeni is accessed by these threads before it is necessarily initialized, because the threads are started in the Q1 constructor, and the statement yeni = new Q1(); only assigns yeni after the constructor completes. In this case, it might be better for the threads to use synchronized (liste) instead.
Other than that, having synchronized (list) in the Q1 constructor does not accomplish much, since the main thread does not access or manipulate the contents of list in that section. The only practical effect is that the threads it starts will block when they reach the first call to liste.size() until the main thread exits the synchronized (list) (immediately after starting the two threads). This has the potential to slightly slow down the first thread that runs, but has no effect on the thread-safety or correctness of the program.
I would also recommend reviewing "How to Handle InterruptedException in Java". In this case, I would recommend restoring the interruption status in the exception handler.
Put together, here is a revised example of this code (including other minor changes to remove unused code and boilerplate comments, improve formatting, and ensure consistency with Java naming conventions):
Q1.java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Q1 {
private static Q1 yeni;
public static void main(String[] args) {
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
MyThread thread1 = new MyThread(list);
MyThread thread2 = new MyThread(list);
thread1.start();
thread2.start();
}
}
MyThread.java:
import java.util.*;
public class MyThread extends Thread {
private final List<String> liste;
public MyThread(List<String> liste) {
this.liste = liste;
}
#Override
public void run() {
try {
synchronized (liste) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
sleep(3000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
interrupt();
}
}
}
Output:
Thread number Thread-0 started running.
a1
b1
c1
d1
e1
f1
Thread number Thread-1 started running.
a1
b1
c1
d1
e1
f1

lock() method acquires locks on which object?

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
Lock lck=new ReentrantLock();
public void lockIt(){
lck.lock();
for(int i=0;i<10;i++) {
System.out.println("i : "+ i);
try{Thread.sleep(200);} catch (Exception e){}
}
lck.unlock();
}
public void test()
{
synchronized(this) **// mark 1**
{
for(int j=0;j<10;j++)
{
System.out.println("val is"+j);
try{Thread.sleep(200);}catch (Exception e){}
}
}
}
public static void main(String[] args) {
LockTest obj=new LockTest();
new Thread(new Runnable() {
#Override
public void run() {
obj.lockIt();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
obj.test();
}
}).start();
}
}
}
// In above case when we say lck.lock(); then lock is acquired on
which object actually ? is it "this" or the "lck" itself ?
even if the lock gets acquired on either of "this" or "lck" object
then how diff. threads are able to enter into the critical sections
locked by the same "this" or "lck" object.
case 1: when we use synchronized(this) at mark1..
case 2: when we use synchronized(lck ) at mark 1..
in both the cases both the loops runs in parallel.
The lock obtained by lck.lock() (which is on the lck object) is completely unrelated to the lock obtained by synchronized(this) or synchronized(lck).
If you want to protect critical sections, then all threads have to use the same locking mechanism (and the same lock).
java.util.concurrent.locks.Lock is a different mechanism introduced for cases where the synchronized keyword is not flexible enough. In particular, the synchronized keyword automatically obtains and releases locks as execution enters and leaves a block. It is not possible there to obtain a lock in one method, store it somewhere, leave the method and release the lock sometime later. With the Lock object you can do these things (and it also offers lock wait timeouts, whereas synchronized will potentially block forever).
#Thilo has answered most of it, just to add one point from your code, ensure that you are unlocking in the finally block as shown below, otherwise, there is a possibility that you will be ending up with a dead lock.
public void lockIt(){
lck.lock();
try {
for(int i=0;i<10;i++) {
System.out.println("i : "+ i);
try{Thread.sleep(200);}catch (Exception e){}
}
} finally { //important
if(lck != null) {
lck.unlock();
}
}
}

Pause Thread after a method is called

Basically I want to pause my Thread after I called a method, before continuing to the other one. I can't loop, my method can only be ran once.
The idea behind this, is to be used in a game, where the methods will display messages, and each time a user presses a key, the next message sould be shown. I can't just go through a list, as the game takes input from the user. I looket at Thread.pause() and Thread.resume() but they woN't work either, and are deprecated.
My current code (Which isn't working):
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
private boolean shouldThreadRun = true;
private boolean storyRunning = true;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(storyRunning) {
synchronized (lock) {
if(!shouldThreadRun) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Looping");
}
}
});
thread = new Thread(() -> {
synchronized (lock) {
pauseThread();
System.out.print("A");
pauseThread();
System.out.print("B");
}
});
managerThread.start();
thread.start();
}
public void pauseThread() {
shouldThreadRun = false;
}
public void resumeThread() {
shouldThreadRun = true;
}
Take a look at my edits and see if it is any similar to what you were trying to achieve. I'm using a scanner to simulate user input, just press enter on your keyboard to try it out.
By the way I hope this is just an exercise and not a real life situation. You should try to avoid this kind of low level management of multithreading in a real product, unless really necessary, in which case you should still use appropriate data structures meant for this. In a real application buttons will be linked to callbacks and you will set some onClick() method to execute the code you need, as soon as the button is pressed.
For what concerns concurrency, I strongly suggest you to take a look at these tutorials: Oracle-Concurrency
PS: notice that I'm completely ignoring interrupts, which is a bad practice, those exception should be handled the right way: I was just trying to achieve the desired result by keeping the code as simple as possible. Also, like someone else pointed out, you should handle spurious wakeups by just calling the wait inside a loop.
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
Scanner in;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(true) {
in = new Scanner(System.in);
in.nextLine();
resumeThread();
}
});
thread = new Thread(() -> {
synchronized (lock) {
while(true){
System.out.print("A");
try {
lock.wait();
} catch (InterruptedException e) {}
System.out.print("B");
try {
lock.wait();
} catch (InterruptedException e) {}
}
}
});
managerThread.start();
thread.start();
}
public void resumeThread() {
synchronized(lock){
lock.notify();
}
}
The first rule of Object.wait, as described in the documentation, is that it must be called in a loop which depends on the condition which is the basis for the wait.
So, your wait needs to look like this:
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
}
An interrupt is not something that happens by accident. A thread is only interrupted if another thread explicitly asks it to stop what it’s doing and exit cleanly.
Therefore, if you get an interrupt, the correct course of action is not to ignore it and print a stack trace. You need to exit cleanly.
The easiest way to do this is to simply enclose your entire while loop in a try/catch:
try {
while (storyRunning) {
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
System.out.println("Looping");
}
}
} catch (InterruptedException e) {
System.out.println("Exiting, because someone asked me to stop.");
e.printStackTrace();
}
This way, your while-loop will automatically exit when interrupted.
Lastly, Object.wait is useless unless another thread calls Object.notify or Object.notifyAll on the very same object on which the waiting thread is synchronized. The wait method will (probably) never return unless the object gets a notify:
public void pauseThread() {
synchronized (lock) {
shouldThreadRun = false;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
public void resumeThread() {
synchronized (lock) {
shouldThreadRun = true;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
Notice that the synchronizing is inside the methods. If you keep your thread synchronized on lock all the time, the manager thread will never have a chance to run at all, because it’s trying to acquire a synchronization lock on the same object. (However, the opposite is not true; the manager thread can stay synchronized on lock all the time, because the wait() method will temporarily release the synchronization lock, allowing the other thread to proceed.)
If all code which accesses shouldThreadRun is inside synchronized blocks, you don’t need to (and should not) make shouldThreadRun volatile, since the synchronization already ensures multi-threaded consistency.

How to restrict specific number of threads to synchronized block in java

I am not able to figure out this question. In a multi threaded environment - exactly 3 threads should be able to execute the synchronized block and rest should wait ?
What I understand is when we use synchronization or monitor one thread will wait until the other thread finishes its execution in side synchronized block or method. To achieve multiple thread to enter inside synchronized block or method we need to use wait(), notify(), notifyAll() i.e. inter thread communication, where wait() method when called on certain object it will takes its lock and give chances to other waiting threads.
So, I am wondering how to do the above question. I am not sure if I have put my question in right way. If its possible do we need to use java concurrent util package or can it be done in basic(core) thread functionality.
Use a semaphore with three permits:
Semaphores are often used to restrict the number of threads that can
access some (physical or logical) resource.
Using a semaphore would probably be the best solution to your problem, but it doesn't hurt to try your own solution, even though it's just for the sake of experimenting and maybe learning something new.
Here is a quick example of a lock implementation using LinkedBlockingQueue. This lock will only allow a certain number of threads to access the block of code between getKey() and returnKey():
public class Lock {
private int keys;
private LinkedBlockingQueue<Integer> q;
public Lock(int keys) throws InterruptedException {
q = new LinkedBlockingQueue<>();
while (q.size() != keys)
q.put(0);
}
public void getKey() throws InterruptedException {
q.take();
}
public void returnKey() throws InterruptedException {
q.put(0);
}
static Lock lck;
public static void main (String [] args) throws InterruptedException {
lck = new Lock(3);
Runnable r = new Runnable() {
#Override
public void run() {
try {
lck.getKey();
Lock.test();
lck.returnKey();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
for (int t = 0; t < 10; t ++)
new Thread(r).start();
}
public static void test() throws InterruptedException {
System.out.println("I am " + Thread.currentThread().getName());
Thread.sleep(1000);
}
}

Java Synchronization -IllegalMonitorStateException

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.

Categories