Creating deadlock situation with different actions (methods) on the same object? - java

I have created the next simple class code (which is just for my question clarification):
public class StudioClass {
synchronized void dancing(String name) {
System.out.println(name + " is dancing");
}
synchronized void singing(String name) {
System.out.println(name + " is singing");
}
public class StudentA extends Thread {
String name;
public StudentA(String name) {
this.name = name;
}
#Override
public void run() {
dancing(name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
singing(name);
}
}
public class StudentB extends Thread {
String name;
public StudentB(String name) {
this.name = name;
}
#Override
public void run() {
singing(name);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
dancing(name);
}
}
In this example the order actions of student A are: dancing and then singing and student B are: singing and than dancing. This scenario is a classic situation for a Deadlock.
How can I deliberately create a Deadlock situation by these actions?
The simple solution (as I understand) is to define each action (singing & dancing) as different objects, but I wonder is there any other way keeping them as methods?

I don't see any potential deadlocks with your code.
A thread executes a single synchronized method and during this execution I don't see conditions which will make two threads to wait for each other in a indefinite way.
At worst, a thread waits for that the other thread releases the lock on the method.
You should imagine a more complex scenario with share object between threads or inter-dependencies between actions.

You're not using any shared resource. Without that there's no question of a deadlock.
If there was a situation like A, B both require a lock on shared variables s,t to perform a dance and song and the locks were acquired in the following way (among others):
A_lock(s)
A_lock(t)
dance
sing
A_release(t)
A_release(s)
B_lock(t)
B_lock(s)
dance
sing
B_release(s)
B_release(t)
There is a chance of deadlock if A acquires s and B acquires t and wait for each other to release locks for eternity.

Related

What is the correct way to avoid an empty synchronized block?

Recently I've started looking into multithreading, and I have a question, perhaps more experienced ones could help.
My program creates two parallel threads, each of them prints counts from 0 to 19 (the NumbersPrinter class, which implements the Runnable interface).
class NumbersPrinter implements Runnable {
private Mediator mediator;
private String name;
private int makeActionOnCount;
public NumbersPrinter(Mediator mediator, String name, int makeActionOnCount) {
this.mediator = mediator;
this.name = name;
this.makeActionOnCount = makeActionOnCount;
}
#Override
public void run() {
for(int i = 0; i<20; i++){
try {
synchronized(this.mediator) {
if(this.mediator.actionInProgress.get()) {
System.out.println(name + " waits");
wait();
}
}
System.out.println(this.name + " says " + i);
Thread.sleep(500);
if(i == makeActionOnCount) {
synchronized(this.mediator) {
System.out.println(this.name + " asks Mediator to perform action...");
this.mediator.performAction();
this.mediator.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
When one of the threads reaches a certain number (defined in the makeActionOnCount variable), it starts performing a certain action that stops the execution of the second counter. The action lasts 5 seconds and after that both counters continue to count.
The counters are interconnected through an instance of the Mediator class, the performAcyion() method also belongs to the instance of the Mediator class.
import java.util.concurrent.atomic.AtomicBoolean;
class Mediator {
public AtomicBoolean actionInProgress = new AtomicBoolean(false);
public Mediator() {
}
public void performAction() throws InterruptedException {
actionInProgress.set(true);
System.out.println("Action is being performed");
Thread.sleep(5000);
System.out.println("Action has been performed");
actionInProgress.set(false);
}
}
Here's the Main class:
class Main {
public static void main(String[] args) throws InterruptedException{
Mediator mediator = new Mediator();
NumbersPrinter data = new NumbersPrinter(mediator, "Data", 10);
NumbersPrinter lore = new NumbersPrinter(mediator, "Lore", 5);
Thread oneThread = new Thread(data);
Thread twoThread = new Thread(lore);
System.out.println("Program started");
oneThread.start();
twoThread.start();
oneThread.join();
twoThread.join();
System.out.println("Program ended");
}
The way the program is written now - works fine, but I don't quite understand what exactly should I write in the first synchronized block, because if you delete all content from it, the program still works, since the counter that does not execute the performAction() method stops 'cause the counter cannot access the monitor of the Mediator object 'cause it is busy with the parallel counter. AtomicBoolean variable and checking it also makes no sense.
In other words, I may not use the wait () and notify () constructs at all, as well as the value of the AtomicBoolean variable, and just check access to the Mediator object's monitor every new iteration using an empty synchronized block. But I've heard that an empty synchronized block is a bad practice.
I am asking for help on how to rewrite the program to use the synchronized block and the wait() and notify() methods correctly.
Maybe I'm syncing on the wrong object? How would you solve a similar problem?
Thanks in advance

Locking all the strings in a collection

I have a collection of strings which must be locked upon by a thread for computing some information. These strings are nothing but unique entities which must be handled by only one thread at a time. Any thread other than the current thread trying to acquire lock on any of these entities in the collection must wait for the current thread to complete its execution and release the lock on the collection. Two entirely different collection containing different strings can be worked upon by two different threads concurrently. I am stuck how to implement this. I tried googling. But all I found was how to lock a single string not many strings. Any idea would be helpful.
For example,
Thread one is working on apple, oranges and bananas.
Thread two wants to works on apple and peaches.
Thread two must wait until Thread one releases the lock.
Update:
Instead of looking upon the lock literally think of it as a permit to use the entity. For example, if you need to use apple, you must acquire permission. The thread must block until it gets permission for all the entities in its collection.
Let met put it in this way. Thread1 [apples, oranges, bananas] seeks permission to use the entities in the collection to a Manager. Lets assume the manager gave permission to Thread1. If another thread Thread2 [apples, peaches] seeks permission, the Manager should not give permission since permission for apples is already owned by Thread1 and Thread2 must be blocked. Once Thread1 tells the manager that it has completed its work, the Manager can give permission to Thread2. Meanwhile, if another thread Thread3 [guava, pineapple] seeks permission, the Manager should not block it and grant permission readily.
Instead of operating on many lock I would choose one synchronized storage of "locked" Strings.
That would hugely simplify synchronization.
Something like that:
private final Set<String> elementsInProgress = new HashSet<String>(); // not thread-safe, accessed only from blocks synchronized on it
public void process(Collection<String> input) throws InterruptedException {
for (String stringToProcess : input) {
synchronized (elementsInProgress) {
while (elementsInProgress.contains(stringToProcess)) {
elementsInProgress.wait();
}
elementsInProgress.add(stringToProcess);
}
doProcess(stringToProcess);
synchronized (elementsInProgress) {
elementsInProgress.remove(stringToProcess);
elementsInProgress.notifyAll();
}
}
}
private void doProcess(String s){/* ... */}
The code snippet is untested, btw )
How about starting with guava-libraries
import com.google.common.collect.Interners;
import com.google.common.collect.Interner;
Then create an an interner. Weak references are OK b/c it's the particular instance that holds the lock. You could use a ConcurrentMap (careful to use putIfAbsent) to do your interning, but...
Interner<String> namedLocks = Interners.newWeakInterner();
Then the client threads can simply use synchronized. I'm using Callable to represent the work.
public <T> void doWork(String name, Callable<T> work) {
synchronized(namedLocks.intern("name")) {
return work.call();
}
}
This will work if Thread 1 (apple, oranges, bananas) and Thread 2 (apple, peaches) can work on (for example) "oranges" and "peaches" concurrently. The 'work' variable in this case represents the work of 'oranges' independently.
If Thread 2 must wait until Thread 1 is done with all three items before starting any of its own, then it's a bit more complex but still manageable. The 'work' in this case represents 'apple+oranges+bananas'.
public <T> T doWork(List<String> names, Callable<T> work) {
// important to avoid deadlocks
names = new ArrayList<>(names);
Collections.sort(names);
return doWorkInternal(names.iterator());
}
private <T> T doWorkInternal(Iterator<String> names, Callable<T> work) {
if(names.hasNext()) {
synchronized(namedLocks.intern(names.next())) {
return doWorkInternal(names, work);
}
} else { // no more locks to acquire
return work.call();
}
}
In the above, you're acquiring each lock in sorted order (important for deadlock) as you recurse down the stack.
public class FruitRunnable implements Runnable {
// this is the actual lock
private static final Object lock = new Object();
// here we store which objects are currently used
private static final Set<String> usedObjects = new HashSet<String>();
// these are the objects a thread will need
private final String[] neededObjects;
public FruitRunnable(String... neededObjects) {
this.neededObjects = neededObjects;
}
#Override
public void run() {
acquireLock(neededObjects);
// between these two methods we can assure that there is
// no other thread working on our resources
work();
// important! release the resources afterwards!
releaseLock(neededObjects);
}
private void work() {
System.out.println("working: " + Arrays.toString(neededObjects));
try {
// work of 10 seconds
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void acquireLock(String[] fruits) {
// go into lock
synchronized (lock) {
// loop until we can acquire our resources
boolean success = false;
while (!success) {
success = true;
for (String s : fruits) {
if (usedObjects.contains(s)) {
// too bad this fruit is already in use
success = false;
}
}
// on success add all used fruits to the usedObjects Set and return
if (success) {
for (String s : fruits) {
usedObjects.add(s);
}
return;
}
// if we had no success we will wait until some other thread
// releases fruits
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void releaseLock(String[] fruits) {
synchronized (lock) {
// release the fruits and notify the other threads to re-check
for (String s : fruits) {
usedObjects.remove(s);
}
lock.notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
// starting the threads from your example
new Thread(new FruitRunnable("apple", "oranges", "bananas")).start();
new Thread(new FruitRunnable("apple", "peaches")).start();
Thread.sleep(2000);
new Thread(new FruitRunnable("guava", "pineapple")).start();
}
}
Find some comments on how it works in code.

How do i prevent my consumer-threads from removing the last element twice?

Questions:
Why do I get a NoSuchElementException when trying to remove the last
element?
How can I fix that?
I have 3 classes (see below) that add/remove Integers to a LinkedList.
Everything works fine until the removing Threads get to the last element.
It seems like both threads try to remove it. The first one succeeds, the second one canĀ“t.
But I thought the synchronized-method/synchroniced-attribute + !sharedList.isEmpty() would handle that.
Class Producer:
This class is supposed to created random numbers, put them in the sharedList, write to console that it just added a number and stop once it gets interrupted. Only 1 thread of this class is expected.
import java.util.LinkedList;
public class Producer extends Thread
{
private LinkedList sharedList;
private String name;
public Producer(String name, LinkedList sharedList)
{
this.name = name;
this.sharedList = sharedList;
}
public void run()
{
while(!this.isInterrupted())
{
while(sharedList.size() < 100)
{
if(this.isInterrupted())
{
break;
} else
{
addElementToList();
}
}
}
}
private synchronized void addElementToList()
{
synchronized(sharedList)
{
sharedList.add((int)(Math.random()*100));
System.out.println("Thread " + this.name + ": " + sharedList.getLast() + " added");
}
try {
sleep(300);
} catch (InterruptedException e) {
this.interrupt();
}
}
}
Class Consumer: This class is supposed to remove the first element in the sharedList, if it exists. The execution should continue (after being interrupted) until sharedList is empty. Multiple (atleast 2) threads of this class are expected.
import java.util.LinkedList;
public class Consumer extends Thread
{
private String name;
private LinkedList sharedList;
public Consumer(String name, LinkedList sharedList)
{
this.name = name;
this.sharedList = sharedList;
}
public void run()
{
while(!this.isInterrupted())
{
while(!sharedList.isEmpty())
{
removeListElement();
}
}
}
private synchronized void removeListElement()
{
synchronized(sharedList)
{
int removedItem = (Integer) (sharedList.element());
sharedList.remove();
System.out.println("Thread " + this.name + ": " + removedItem + " removed");
}
try {
sleep(1000);
} catch (InterruptedException e) {
this.interrupt();
}
}
}
Class MainMethod: This class is supposed to start and interrupt the threads.
import java.util.LinkedList;
public class MainMethod
{
public static void main(String[] args) throws InterruptedException
{
LinkedList sharedList = new LinkedList();
Producer producer = new Producer("producer", sharedList);
producer.start();
Thread.sleep(1000);
Consumer consumer1 = new Consumer("consumer1", sharedList);
Consumer consumer2 = new Consumer("consumer2", sharedList);
consumer1.start();
consumer2.start();
Thread.sleep(10000);
producer.interrupt();
consumer1.interrupt();
consumer2.interrupt();
}
}
Exception: This is the exact exception I get.
Exception in thread "Thread-2" java.util.NoSuchElementException at
java.util.LinkedList.getFirst(LinkedList.java:126) at
java.util.LinkedList.element(LinkedList.java:476) at
Consumer.removeListElement(Consumer.java:29) at
Consumer.run(Consumer.java:20)
Your exception is rather simple to explain. In
while(!sharedList.isEmpty())
{
removeListElement();
}
sharedList.isEmpty() happens outside of synchronization and so one consumer can still see a list as empty while another consumer has already taken the last element.
The consumer that wrongfully believed it is empty will not try to remove an element that is no longer there which leads to your crash.
If you want to make it threadsafe using a LinkedList you'll have to do every read / write operation atomic. E.g.
while(!this.isInterrupted())
{
if (!removeListElementIfPossible())
{
break;
}
}
and
// method does not need to be synchronized - no thread besides this one is
// accessing it. Other threads have their "own" method. Would make a difference
// if this method was static, i.e. shared between threads.
private boolean removeListElementIfPossible()
{
synchronized(sharedList)
{
// within synchronized so we can be sure that checking emptyness + removal happens atomic
if (!sharedList.isEmpty())
{
int removedItem = (Integer) (sharedList.element());
sharedList.remove();
System.out.println("Thread " + this.name + ": " + removedItem + " removed");
} else {
// unable to remove an element because list was empty
return false;
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
this.interrupt();
}
// an element was removed
return true;
}
The same problem exists within your producers. But they would just create a 110th element or something like that.
A good solution to your problem would be using a BlockingQueue. See the documentation for an example. The queue does all the blocking & synchronization for you so your code does not have to worry.
Edit: regarding 2 while loops: You don't have to use 2 loops, 1 loop loops enough but you'll run into another problem: consumers may see the queue as empty before the producers have filled it. So you either have to make sure that there is something in the queue before it can be consumed or you'll have to stop threads manually in other ways. You thread.sleep(1000) after starting the producer should be rather safe but threads are not guaranteed to be running even after 1 second. Use e.g. a CountDownLatch to make it actually safe.
I am wondering why you are not using the already existing classes that Java offers. I rewrote your program using those, and it becomes much shorter and easier to read. In addition the lack of synchronized, which blocks all threads except for the one who gets the lock (and you even do double synchronization), allows the program to actually run in parallel.
Here is the code:
Producer:
public class Producer implements Runnable {
protected final String name;
protected final LinkedBlockingQueue<Integer> sharedList;
protected final Random random = new Random();
public Producer(final String name, final LinkedBlockingQueue<Integer> sharedList) {
this.name = name;
this.sharedList = sharedList;
}
public void run() {
try {
while (Thread.interrupted() == false) {
final int number = random.nextInt(100);
sharedList.put(number);
System.out.println("Thread " + this.name + ": " + number);
Thread.sleep(100);
}
} catch (InterruptedException e) {
}
}
}
Consumer:
public class Consumer implements Runnable {
protected final String name;
protected final LinkedBlockingQueue<Integer> sharedList;
public Consumer(final String name, final LinkedBlockingQueue<Integer> sharedList) {
this.name = name;
this.sharedList = sharedList;
}
public void run() {
try {
while (Thread.interrupted() == false) {
final int number = sharedList.take();
System.out.println("Thread " + name + ": " + number + " taken.");
Thread.sleep(100);
}
} catch (InterruptedException e) {
}
}
}
Main:
public static void main(String[] args) throws InterruptedException {
final LinkedBlockingQueue<Integer> sharedList = new LinkedBlockingQueue<>(100);
final ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(new Producer("producer", sharedList));
Thread.sleep(1000);
executor.execute(new Consumer("consumer1", sharedList));
executor.execute(new Consumer("consumer2", sharedList));
Thread.sleep(1000);
executor.shutdownNow();
}
There are several differences:
Since I use a concurrent list, I do not have to care (much) about synchronization, the list does that internally.
As this list uses atomic locking instead of true blocking via synchronized it will scale much better the more threads are used.
I do set the limit of the blocking queue to 100, so even while there is no check in the producer, there will never be more than 100 elements in the list, as put will block if the limit is reached.
I use random.nextInt(100) which is a convenience function for what you used and will produce a lot less typos as the usage is much clearer.
Producer and Consumer are both Runnables, as this is the preferred way for threading in Java. This allows to later on wrap any form of thread around them for execution, not just the primitive Thread class.
Instead of the Thread, I use an ExecutorService which allows easier control over multiple threads. Thread creation, scheduling and other handling is done internally, so all I need to do is to choose the most appropriate ExecutorService and call shutdownNow() when I am done.
Also note that there is no need to throw an InterruptedException into the void. If the consumer/producer is interrupted, that is a signal to stop execution gracefully as soon as possible. Unless I need to inform others "behind" that thread, there is no need to throw that Exception again (although no harm is done either).
I use the keyword final to note elements that won't change later on. For once this is a hint for the compiler that allows some optimizations, it as well helps me to prevent an accidental change of a variable that is not supposed to change. A lot of problems can be prevented by not allowing variables to change in a threaded environment, as thread-issues almost always require something to be read and written at the same time. Such things cannot happen if you cannot write.
Spending some time to search through the Java library for the class that fits your problem the best usually solves a lot of trouble and reduces the size of the code a lot.
Try to switch places of
while(!sharedList.isEmpty())
and
synchronized(sharedList)
I don't think you need synchronized on removeListElement().

Why this is not right by using synchronized (Java concurrency) in this example?

I have two Java classes as below...
(1) JavaClass SyncTest: It defines a class (implementing Runnable) and invokes a "synchronized" method (named "call") defined in Class SyncTestCalled
(2) JavaClass SyncTestCalled : There is one synchronized method.
------
After calling from main(), I am thinking it should output something like:
[Two]
[Three]
[One]
But, it outputs something like this (note the open bracket which is not paired in right locations) :
[[[Two]
Three]
One]
What's wrong with the codes? Please help. Thanks a lot!
Here is the code of these two classes...
public class SyncTest implements Runnable {
Thread t;
String name;
SyncTestCalled syncTestCalled;
public SyncTest(String name) {
t = new Thread(this, name);
syncTestCalled = new SyncTestCalled();
this.name = name;
t.start();
}
public void run() {
syncTestCalled.call(this.name);
}
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest("One");
SyncTest syncTest2 = new SyncTest("Two");
SyncTest syncTest3 = new SyncTest("Three");
}
} // of class SyncTest
public class SyncTestCalled {
public SyncTestCalled() {
// Do nothing
}
synchronized public void call(String message) {
System.out.print("[");
try {
Thread.sleep(1000);
System.out.print(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("]");
}
} // of class SyncTestCalled
When you use synchronized as part of the method declaration, Java attempts to acquire the monitor (lock) on the object the method is invoked on. So a method like
synchronized public void call(String message) {
...
}
is equivalent to
public void call(String message) {
synchronized (this) {
...
}
}
In your code, you create three different SyncTestCalled objects and pass each individual one to the different SyncTest instances. In other words, nothing is coordinated. Each call to
syncTestCalled.call(this.name);
is synchronized on a different object and therefore none of the threads need to wait on the others.
It's up to the Thread scheduler who gets where first, so you get output like
[[[Two]
Three]
One]
or
[[[OneThree]
Two]
]
Note that Thread.sleep(long) does not relinquish any monitors the thread currently has.
Only one thread can invoke your call() method on a given instance at any given time. But what you want is atomicity for several calls to System.out.print() methods. For that, you need to acquire a lock on System.out instead:
synchronized (System.out) {
System.out.print('[');
System.out.print(message);
System.out.println(']');
}
Because PrintStream locks on itself, this will prevent other threads from interleaving their own calls to print().

Understanding synchronized

Given this code:
public class Messager implements Runnable {
public static void main(String[] args) {
new Thread(new Messager("Wallace")).start();
new Thread(new Messager("Gromit")).start();
}
private String name;
public Messager(String name) { this.name = name; }
public void run() {
message(1); message(2);
}
private synchronized void message(int n) {
System.out.print(name + "-" + n + " ");
}
}
I understand that the synchronized keyword makes the thread dependent on the object's lock. Questions:
a) Is the lock released as soon as the method marked as synchronized finishes? Or as soon as the thread's run() method finishes
b) Can I ensure that any one of the threads will print its name and 1 2 before the other?
A. Yes. It's released as soon as the synchronized function finishes.
B. Yes. You can, but if you wanted to do so, why would you write multithreaded code in the first place? synchronized guarantees atomicity, not anything regarding the order, but you can enforce order by waiting for a flag to change. Anyway, what you are trying to enforce is sequentiality. You get this for free in single-threaded environments :)

Categories