I'm studying how to synchronize methods and blocks in Java in order to avoid race condition and I tried to solve an exercise in both ways. The problem is that if I try to use synchronized block everything works fine but with synchronized method it get stuck. I thought that I could use both way with not really big differences(maybe one of them reduce parallelism in some case but I'm not sure about this). I'm wondering what's wrong in my code and I want to ask If there's any case where It's preferible using synchronized block instead of synchronized method.
//Not working
import java.util.Random;
class MultiplicationTable extends Thread {
private Cont obj;
private int number;
private Random r;
public MultiplicationTable(Cont o, int num) {
obj = o;
number = num;
r = new Random();
start();
}
public void run() {
for (int j = 0; j < 10; j++) {
for (int i = 0; i < number; i++) {
obj.incr();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName() + ": " + obj.getVal());
}
try {
Thread.sleep(r.nextInt(2000));
} catch (InterruptedException e) {
}
}
}
class Cont {
private int count = 0;
private boolean available = false;
public synchronized void incr() {
while (available) {
try {
wait();
} catch (InterruptedException e) {
// TODO: handle exception
}
}
available = true;
count++;
notifyAll();
}
public synchronized int getVal() {
while (!available) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
}
available = false;
notifyAll();
return count;
}
}
public class Es3 {
public static void main(String[] args) {
Cont obj = new Cont();
int num = 5;
MultiplicationTable t1 = new MultiplicationTable(obj, num);
MultiplicationTable t2 = new MultiplicationTable(obj, num);
}
}
//Working
import java.util.Random;
class MultiplicationTable extends Thread {
private Cont obj;
private int number;
private Random r;
public MultiplicationTable(Cont o, int num) {
obj = o;
number = num;
r = new Random();
start();
}
public void run() {
synchronized (obj) {
for (int j = 0; j < 10; j++) {
for (int i = 0; i < number; i++) {
obj.incr();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
System.out.println(Thread.currentThread().getName() + ": " + obj.getVal());
}
try {
Thread.sleep(r.nextInt(2000));
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
}
class Cont {
private int count = 0;
public void incr() {
count++;
}
public int getVal() {
return count;
}
}
public class Es3 {
public static void main(String[] args) {
Cont obj = new Cont();
int num = 5;
MultiplicationTable t1 = new MultiplicationTable(obj, num);
MultiplicationTable t2 = new MultiplicationTable(obj, num);
}
}