java ReentrantLock tryLock() misunderstanding - java

ReentrantLock l = new ReentrantLock(true);
Reader[] readers = new Reader[2];
for (int i = 0; i < readers.length; i++) {
readers[i] = new Reader(l);
}
for (int i = 0; i < readers.length; i++) {
readers[i].start();
}
public class Reader extends Thread {
private ReentrantLock l;
public Reader(ReentrantLock l) {
this.l = l;
}
#Override
public void run() {
try {
l.tryLock();
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " i = " + i);
Thread.sleep(500);
}
// l.unlock(); // although it commented the code not hanged why?
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
according to my understanding to tryLock() Acquires the lock if it is not held by another thread and returns immediately now in my case i have two threads suppose thread_0 get lock now i have two questions :
Q1: why thread_1 still enter the critical section after l.tryLock() isn't it locked by thread_0;
Q2: isn't it supposes to my code to be hanged because thread_0 doesn't release the lock
#thanks advance

Your code is entering the critical section because, tryLock() is not a blocking function, it will return true or false immediately, and proceed with the "Critical Section" code snippet below.
In the documentation of tryLock() you can read
If the lock is held by another thread then this method will return
immediately with the value false.
So you need to call lock() method, which waits until the lock is released by another reader.

Related

Multithreading matrix multiplication in Java

i'm trying to build a program for multiplying two matrices (A[a,b], B[c,d]) using a*d threads (that will be used to print the sum of one index in the finished matrix), for this purpose, i'm using a 'monitor' class that will be used as a controller to synchrosize between the threads, 'multiplier' class to represent the single thread and a main program class. My idea is that the threads will have their calculations, and when thread(0,0) will print his sum, he will signal the next in line. For some reason after printing the first index - all the threads stay in waiting mode and won't test my condition. Could you look at my code and tell me where is my mistake?
Monitor class:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
final class Monitor {
private Lock lock;
int index;
Condition cond;
public Monitor () {
lock = new ReentrantLock();
cond = lock.newCondition();
this.index = 0;
}
public synchronized void finished(int x, double sum) throws InterruptedException {
lock.lock();
if(index != x) {
while(index != x) cond.await();
System.out.printf("%9.2f ",sum);
index++;
lock.unlock();
cond.signalAll();
}
else {
System.out.printf("%9.2f ",sum);
index++;
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
}
if(index % 5 == 0) System.out.println();
}
}
Multiplier:
public class Multiplier extends Thread {
private int index;
private double [] vectorOne;
private double [] vectorTwo;
private Monitor monitor;
private double sum;
//constructor
public Multiplier(int index, Monitor monitor,double [] vectorOne,double [] vectorTwo) {
this.index = index;
this.monitor = monitor;
this.vectorOne = vectorOne;
this.vectorTwo = vectorTwo;
}
public void VecMulti() {
sum = 0;
for (int i = 0 ; i < vectorOne.length ; i++)
sum += vectorOne[i] * vectorTwo[i];
}
public double getSum() {
return sum;
}
public void run() {
VecMulti();
try {
monitor.finished(index, sum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main class:
public class MatrixMultiTest {
public static void main(String[] args) {
Monitor monitor = new Monitor(3*5);
Matrix A = Matrix.random(3,4);
Matrix B = Matrix.random(4,5);
System.out.println("Matrix No1");
A.show();
System.out.println();
System.out.println("Matrix No2");
B.show();
System.out.println();
System.out.println("Multi Matrix");
for (int i = 0; i < 3; i++)
for (int j = 0; j < 5; j++) {
Multiplier myThr = new Multiplier(i*5+j,
monitor,A.getRow(i),B.getCol(j));
myThr.start();
try {
myThr.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The finished() method is riddled with problems:
The first problem is the synchronized keyword. It must be removed. With this keyword, if the first entering thread has a non-zero index, the program will deadlock - the thread will forever be parked waiting for the condition to signal, which will never come, because no other thread can enter the finished() method.
The second fault lies with the else block:
else {
System.out.printf("%9.2f ",sum);
index++;
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
try { lock.unlock(); }
catch (java.lang.IllegalMonitorStateException e) {};
}
It never invokes cond.signalAll(), so after the thread with index=0 gets through, others will stay parked forever.
The third problem is that in if(index != x) {.. block, cond.signalAll() and lock.unlock() come in wrong order:
lock.unlock();
cond.signalAll();
Condition's signalAll() method documentation states:
An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called. Implementations must document this precondition and any actions taken if the lock is not held. Typically, an exception such as IllegalMonitorStateException will be thrown.
These two lines of code must be switched in order, or an IllegalMonitorStateException will be thrown.
A working version of the method can look something like this:
public void finished(int x, double sum) throws InterruptedException {
try {
lock.lock();
while (index != x) {
cond.await();
}
System.out.printf("%9.2f ", sum);
index++;
cond.signalAll();
} finally {
lock.unlock();
}
if (index % 5 == 0) System.out.println();
}
Funny enough, the code provided by OP actually works even with all these faults, but only due to this block of code in the MatrixMultiTest class:
try {
myThr.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Every thread is created and then started and joined sequentially, thus only one thread ever tries to acquire the implicit lock on the synchronized finished() method at any moment in time, and i*5+j index value ensures that the threads acquire this implicit lock in order of their index: 0, 1, 2 etc. It means that inside the method, index is always equal to x, and every thread goes through else block in finished(), allowing the program to complete execution. cond.await() is actually never invoked.
If the join block is removed, then some values might get printed, but the program will eventually deadlock.

Why is my producer consumer deadlocking (or livelocking)?

I am trying to implement a typical producer consumer using reentrant locks.
Producer thread prints even numbers and consumer threads print odd numbers.
Here is my Code, But for some reason it is deadlocking
The runnable tasks
public class EvenPrinterRunnable implements Runnable {
SharedBuffer buf;
public EvenPrinterRunnable(SharedBuffer buf) {
this.buf = buf;
Thread.currentThread().setName("Even Runnable");
}
#Override
public void run() {
for(int i = 0; i < 10; i++) {
buf.printEven();
}
}
}
public class OddPrinterRunnable implements Runnable {
SharedBuffer buf;
public OddPrinterRunnable(SharedBuffer buf){
this.buf = buf;
Thread.currentThread().setName("ODD Runnable");
}
#Override
public void run(){
for(int i = 0; i < 10; i++){
buf.printOdd();
}
}
}
The shared Buffer
public class SharedBuffer {
Lock lock = new ReentrantLock();
Condition evenNotPrinted = lock.newCondition();
Condition oddNotPrinted = lock.newCondition();
int currentNumber = 0;
public void printEven() {
System.out.println("from even");
try {
lock.lock();
try {
oddNotPrinted.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
currentNumber++;
evenNotPrinted.signalAll();
}
finally {
lock.unlock();
}
}
public void printOdd() {
System.out.println("from odd");
try {
lock.lock();
try {
evenNotPrinted.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
currentNumber++;
oddNotPrinted.signalAll();
}
finally {
lock.unlock();
}
}
}
The driver class
public class OddEvenDriver {
public static void main(String[] args) {
//using runnables with lock buffer
SharedBuffer buf1 = new SharedBuffer();
EvenPrinterRunnable epr = new EvenPrinterRunnable(buf1);
OddPrinterRunnable opr = new OddPrinterRunnable(buf1);
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(opr);
es.submit(epr);
es.shutdown();
}
}
It is outputting
from even
from odd
Or
from odd
from even
That means each thread is acquiring the lock and then it waits on a condition evenNotPrinted and oddNotPrinted, and since no one of them can progress until the signal is called, So my question is , shall I signal each condition at the start of the method itself?
What am i missing here
So my question is , shall I signal each condition at the start of the method itself?
No. That won't work. A condition variable does not remember that it previously was signalled when a thread calls condition.await(). The condition.signal() and condition.signalAll() functions do not do anything at all unless some other thread already is waiting for the signal.
Condition variables are a low-level synchronization mechanism that is intended to be used in a very specific way to implement queues and semaphores and other higher-level synchronized objects. The Guarded Blocks tutorial explains it in detail. (Note: the tutorial talks about object.wait() and object.notify() and synchronized blocks, but the concepts all maps directly onto Lock and Condition objects.)
Your basic problem is that your two threads can't be completely symmetrical with one another. One of them has to go first. Your main() thread must either wake one of them up, or construct one with an argument that says, "you first."

Concurrency in Java using synchronized blocks not giving expected results

Below is a trivial java program. It has a counter called "cnt" that is incremented and then added to a List called "monitor". "cnt" is incremented by multiple threads, and values are added to "monitor" by multiple threads.
At the end of the method "go()", cnt and monitor.size() should have the same value, but they don't. monitor.size() does have the correct value.
If you change the code by uncommenting one of the commented synchronized blocks, and commenting out the currently uncommented one, the code produces the expected results. Also, if you set the thread count (THREAD_COUNT) to 1, the code produces the expected results.
This can only be reproduced on a machine with multiple real cores.
public class ThreadTester {
private List<Integer> monitor = new ArrayList<Integer>();
private Integer cnt = 0;
private static final int NUM_EVENTS = 2313;
private final int THREAD_COUNT = 13;
public ThreadTester() {
}
public void go() {
Runnable r = new Runnable() {
#Override
public void run() {
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
// synchronized(cnt) {
// cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
// }
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
// synchronized(cnt) {
// cnt += NUM_EVENTS; // <-- moving the synchronized block here results in the correct value for cnt, no surprise
// }
}
};
Thread[] threads = new Thread[THREAD_COUNT];
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii] = new Thread(r);
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii].start();
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
try { threads[ii].join(); } catch (InterruptedException e) { }
}
System.out.println("Both values should be: " + NUM_EVENTS*THREAD_COUNT);
synchronized (monitor) {
System.out.println("monitor.size() " + monitor.size());
}
synchronized (cnt) {
System.out.println("cnt " + cnt);
}
}
public static void main(String[] args) {
ThreadTester t = new ThreadTester();
t.go();
System.out.println("DONE");
}
}
Ok let's have a look at the different possibilities you mention:
1.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
}
}
First the monitor object is shared between the threads, therefore getting a lock on it (that is what synchronized does) will make sure that the code inside of the block will only be executed by one thread at a time. So the 2 synchronized inside of the outer one are not necessary, the code is protected anyway.
2.
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized( monitor) {
monitor.add(cnt);
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
Ok this one is a little bit tricky. cnt is an Integer object and Java does not allow modifying an Integer object (Integers are immutable) even though the code suggests that this is what is happening here. But what acutally will happen is that cnt++ will create a new Integer with the value cnt + 1 and override cnt.
This is what the code actually does:
synchronized(cnt) {
Integer tmp = new Integer(cnt + 1);
cnt = tmp;
}
The problem is that while one thread will create a new cnt object while all other threads are waiting to get a lock on the old one. The thread now releases the old cnt and will then try to get a lock on the new cnt object and get it while another thread gets a lock on the old cnt object. Suddenly 2 threads are in the critical section, executing the same code and causing a race condition. This is where the wrong results come from.
If you remove the first synchronized block (the one with monitor), then your result gets even more wrong because the chances of a race increase.
In general you should try to use synchronized only on final variables to prevent this from happening.

IllegalMonitorStateException in Thread wait notify

I am working on one task where i am having n threads and each thread will print nth number sequentially[1 to n] .where each thread is waiting and notifying each other .
for Ex:-
if we are having 6 Threads then 1st thread should print 1,2nd thread should print 2 and so on.[in sequence 1 to 6]
when i am running below program i am getting IllegalMonitorStateException .
package interviews;
public class NumerPrintingwithThreadCount {
public static void main(String[] args) throws InterruptedException {
int Max =6;
Integer [] o = new Integer [Max];
for (int i = 0; i < Max; i++) {
o[i] = new Integer(i);
}
PrintingThread []tt = new PrintingThread [Max];
for (int i = 0; i <Max; i++) {
Integer obj1 =o[i];
Integer obj2=null;
if(i==Max-1){
obj2 = o[0];
}
else{
obj2=o[i+1];
}
PrintingThread t=new PrintingThread(obj1, obj2,0);
tt[i]=t;
}
for (int i=tt.length-1; i >=0; i--) {
tt[i].setName("Thread"+1);
tt[i].start();
Thread.sleep(1);
}
}
}
class PrintingThread extends Thread{
Integer object1=null;
Integer object2=null;
int min =0;
public PrintingThread(Integer obj1 ,Integer obj2, int min) {
this.object1=obj1;
this.object2=obj2;
this.min=min;
}
public void run() {
try {
if(min==object1.intValue())
{
object2.notify();
}else{
synchronized (object2) {
object2.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
object2.notify();
}
}
From the Javadoc for Object.notify()
This method should only be called by a thread that is the owner of
this object's monitor. 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.
You must synchronize the object you are calling notify on.
Note: as wait() can either miss a notify or wake spuriously, you should associate a state change with a notify/wait. i.e. check the state change on wait() and introduce a state change on notify()

Sequential execution of threads using synchronized

I have a snippet of code that creates 3 threads and expect them to print sequentially using synchronized block on the integer object. But apparently I am getting deadlock sometimes. See below:
public class SequentialExecution implements Runnable {
private Integer i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized(i) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (i != 2);
synchronized(i) {
second();
i = 3;
}
} else {
while (i != 3);
synchronized(i) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) {
//create 3 threads and call first(), second() and third() sequentially
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
}
}
The result I am expecting(and sometimes getting) is:
first 1
second 2
third 3
One sample result I am getting with deadlock(and eclipse hangs) is:
first 1
second 2
Anyone know why this is not working? I know I can use locks but I just don't know why using synchronized block is not working.
Declare i to be volatile: private volatile Integer i = 1;. This warns the compiler that it must not apply certain optimizations to i. It must be read from memory each time it is referenced in case another thread has changed it.
I also agree with the recommendation in user3582926's answer to synchronize on this rather than i, because the object referenced by i changes as the program runs. It is neither necessary nor sufficient to make the program work, but it does make it a better, clearer program.
I have tested each change by changing the main method to:
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
There is no deadlock. There is a memory order issue.
The while loops in the second and third threads are outside any synchronized block. There is nothing telling the compiler and JVM that those threads cannot keep i, or the object to which it points, in a register or cache during the loop. The effect is that, depending on timing, one of those threads may get stuck looping looking at a value that is not going to change.
One way to solve the problem is to mark i volatile. That warns the compiler that it is being used for inter-thread communication, and each thread needs to watch for changes in memory contents whenever i changes.
In order to solve it entirely using synchronization, you need to check the value of the Integer referenced by i inside a block that is synchronized on a single, specific object. i is no good for that, because it changes due to boxing/unboxing conversion. It might as well be a simple int.
The synchronized blocks cannot wrap the while loops, because that really would lead to deadlock. Instead, the synchronized block has to be inside the loop. If the updates to i are synchronized on the same object, that will force the updates to be visible to the tests inside the while loops.
These considerations lead to the following synchronization-based version. I am using a main method that does 1000 runs, and will itself hang if any thread in any of those runs hangs.
public class SequentialExecution implements Runnable {
private int i = 1;
public void run() {
String tmp = Thread.currentThread().getName();
if (tmp.equals("first")) {
synchronized (this) {
first();
i = 2;
}
} else if (tmp.equals("second")) {
while (true) {
synchronized (this) {
if (i == 2) {
break;
}
}
}
synchronized (this) {
second();
i = 3;
}
} else {
while (true) {
synchronized (this) {
if (i == 3) {
break;
}
}
}
synchronized (this) {
third();
}
}
}
public void first() {
System.out.println("first " + i);
}
public void second() {
System.out.println("second " + i);
}
public void third() {
System.out.println("third " + i);
}
public static void main(String[] args) throws InterruptedException {
// create 3 threads and call first(), second() and third() sequentially
for (int i = 0; i < 1000; i++) {
SequentialExecution se = new SequentialExecution();
Thread t1 = new Thread(se, "first");
Thread t2 = new Thread(se, "second");
Thread t3 = new Thread(se, "third");
t3.start();
t2.start();
t1.start();
t1.join();
t2.join();
t3.join();
}
}
}
I believe you want to be using synchronized(this) instead of synchronized(i).

Categories

Resources