More than one thread inside synchronized methods? [duplicate] - java

This question already has answers here:
Entering in block with an Intrinsic Lock
(2 answers)
Closed 8 years ago.
As I red somewhere, when we have synchronized methods, only one thread can use any of those method at the same time. The problem is that I have small peace of code that looks to break this rule, and I hope some of you knows why.
import java.util.Date;
public class SyncTest extends Thread {
private int state;
public static final int STATE_STOP = 10;
public static final int STATE_DO_TASK = 2;
public static final int STATE_FREE = 0;
public void run() {
try {
while(getThisState() != STATE_STOP) {
if(getThisState() == STATE_DO_TASK) {
Thread.sleep(2000);
setState(0);
}
}
}catch(Exception ex) {
ex.printStackTrace();
}
}
public synchronized void setState(int newState) {
this.state = newState;
this.notify();
}
public synchronized int getThisState() {
return this.state;
}
public synchronized void waitForComplete(int timeoutMilisec) {
try {
while( getThisState() != STATE_FREE) {
wait(timeoutMilisec);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
SyncTest syncTest = new SyncTest();
syncTest.start();
syncTest.setState(STATE_DO_TASK);
System.out.println("Start operation: " + new Date());
syncTest.waitForComplete(30000);
syncTest.setState(STATE_STOP);
System.out.println("End operation: " + new Date());
}
}
What we have here is 'waitForComplete' method, that waits until state equals zero. While main thread waits, second thread is sleeping 5 seconds and then calls setState method. This changes 'state' variable to zero, and calls notify what unlocks waiting in main process. That seems to make sense, but the question is: How the hell it is possible that second thread executes 'setState' when on the same time main thread is inside 'waitForComplete' method. Both methods are synchronized, so it should be impossible to execute them simultaneously.

When you call wait() the thread releases its lock on the monitor, so other threads are free to enter the synchronized block.

Related

Can't relase the lock with notify

I've got a test on java thread coding but i have some basic problem.. after hours of trying and searching I decided to try there!
I can't understand why my wait is still locked even after my notify :
Here you can find my code:
public class Mymain {
public static void main(String[] args) {
for( int i=0;i<100;i++){
new ThreadClass(i).start();
}
}
}
public class ThreadClass extends Thread {
static boolean ok = false;
int id;
public ThreadClass(int i) {
id = i;
}
public void run() {
System.out.println("Thread start " + id);
Last.toDo(id);
if (id == 5)
try {
waiting();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (id != 5)
awaking();
System.out.println("thread end " + id);
}
private synchronized void awaking() {
// TODO Auto-generated method stub
if (ok) {
System.out.println("i'm " + id + " and i'm Awaking 5");
ok = false;
notify();
System.out.println("I did the notify and i'm " + id);
}
}
private synchronized void waiting() throws InterruptedException {
System.out.println("Sleeping");
ok = true;
wait();
System.out.println("Awake 5");
}
}
Result
Then it starts looping or it goes in dead lock not sure.. it should just stop the thread with id=5 and then the next thread should re-start the id = 5.. but thread 5 never wake up after the notify...
In the result as you can see I got 2 threads trying to wake up the thread 5 and thread 5 is always waiting since the start^^
The issue is that you are not calling notify() on the same object that you called wait() on. In particular, thread 5 is calling wait() on itself, but thread 8, for example, is calling notify() on itself, not on thread 5. As a result, thread 5 is never getting notified.
Also, you need to make the ok variable volatile to ensure that when one thread sets it, the other threads can see the change. This isn't causing you a problem in this particular case, but it could cause a problem in other cases.
Why you don't use notifyAll() method? When you invoke notify(), it means that only one thread will change a status from waiting to runnable, but there can be the situations when you have more than one thread and other threads which are waiting in the line as well, they will not receive this notification. In my opinion it is preferable to use notifyAll.
i can't understand why my wait is still locked even after my notify :
Wait and notify work when the same object instance is used. If you for example have:
String x1 = "...";
String x2 = "...";
and thread #1 does:
synchronized (x1) { x1.wait(); }
and thread #2 then does:
synchronized (x2) { x2.wait(); }
Then thread #1 will still be waiting because the notify was only for x2. In your example, the thread with id 5 is waiting on its own instance of ThreadClass since you are using method synchronization. Then when other threads call awaking() they too are calling notify on their instances of ThreadClass. If you want thread #5 to see the other thread's notify then they should share a lock object.
Maybe something like:
final Object lock = new Object();
for (int id = 0; id < 100; id++){
new ThreadClass(id, lock).start();
}
...
public class ThreadClass extends Thread {
private final Object lock;
...
public ThreadClass(int id, Object lock) {
this.id = id;
this.lock = lock;
}
...
private void awaking() {
...
synchronized (lock) {
lock.notify();
}
...
}
private void waiting() throws InterruptedException {
...
synchronized (lock) {
lock.wait();
}
...
}
}
Look I did a few changes to your code:
You can't just notify() , you'll notify to this. And you can't just wait() , you'll wait forever. You have to use these function over an Object, so i added an Integer object (just to show you - you'll have to choose the right object).
You have yo understand between synchronized and static synchronized. A quick search would lead you to a perfect answer.
Why function waiting() is synchronized? only thread number 5 calls it.
When calling to an Object.notify() / Object.wait(), you have to declare a synchronized block over the object.
Here's some code:
public class Threads {
public static void main(String[] args) {
Integer intObject = new Integer(0);
for( int i=0;i<100;i++){
new ThreadClass(i, intObject).start();
}
}
}
class ThreadClass extends Thread {
static boolean ok = false;
int id;
Integer intObject;
public ThreadClass(int i, Integer intObject) {
id = i;
this.intObject = intObject;
}
public void run() {
System.out.println("Thread start " + id);
//Last.toDo(id);
if (id == 5)
waiting();
else
awaking(this);
System.out.println("thread end " + id);
}
private static synchronized void awaking(ThreadClass t) {
if(ok) {
System.out.println("i'm " + t.id + " and i'm Awaking 5");
ok = false;
synchronized (t.intObject) {
t.intObject.notify();
}
System.out.println("I did the notify and i'm " + t.id);
}
}
private void waiting(){
System.out.println("Sleeping");
ok = true;
synchronized (intObject) {
try {
intObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Awake 5");
}
}

Same thread is able to execute on same objects two synchronized methods

As I Know only one thread can execute on a synchronize method on same block but in below producer consumer problem I am able to run both the methods.
Sample Code
import java.util.concurrent.CountDownLatch;
public class VIV {
public static void main(String[] args) throws Exception {
Number no = new Number();
//Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od,"ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev,"Even");
evenThraed.start();
}
}
class Number {
int no;
boolean flag=false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(!flag) {
try {
Thread.sleep(1000);
}catch (Exception e) {
// TODO: handle exception
}
}
no=no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=false;
notify();
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
// wait block so no other thread can enter on same object synchronized method
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
if(flag) {
try{
wait();
}catch (Exception e) {
// TODO: handle exception
}
}
no = no+1;
System.out.println(Thread.currentThread().getName()+":"+no);
flag=true;
notify();
return no;
}
}
class Even implements Runnable {
Number num;
int noOfTime;
Even(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
Number num;
int noOfTime;
Odd(Number no, int noOfTime) {
this.num=no;
this.noOfTime=noOfTime;
}
public void run() {
for(int i=0;i<noOfTime;i++) {
num.getOddNo();
}
}
}
OutPut :
In ODD Method
In Even Method
As Only one Number object is created and passed to other classes which are invoking on its two different synchronized methods. Both methods are printing the message after that waiting .
The reason that both methods get executed at the same time is that the wait() method releases the lock. Once your synchronized method calls wait(), the lock is given back, and another thread can invoke another synchronized method on the same object. Don't call wait() inside a synchronized method in this way!
The wait() calls are also the reason that you're getting deadlock. This is what is happening:
The odd method acquires the lock and starts executing.
The odd method prints its first message.
The odd method invokes wait(), which releases the lock and waits to be notified.
The even method can now acquire the lock that's been released.
The even method prints its first message.
The even method invokes wait(), which releases the lock and waits to be notified.
By this point, you're in the middle of both synchronized methods (because wait() releases the lock), and you're deadlocked (because both methods are waiting).
Don't call wait() unless you're quite sure that's what you need. If your wait() is there just to keep it waiting to see if the synchronization can be broken, you might try Thread.sleep() instead, which will pause without releasing any locks. Usually it's enough to declare the relevant methods or blocks as synchronized without needing any wait / notify.
(By the way, it's not a good idea to have a class called Number, because this is a standard JDK class. It's the superclass of Double, Integer, and so on.)
I don't know whether you are trying to achieve this kind of thing, if you are trying to call EVEN & ODD alternatively, then I have modified your code for the same. Have a look at below code :-
public class VIV {
public static void main(String[] args) throws Exception {
TestNumber no = new TestNumber();
// Same Object is passed
Even ev = new Even(no, 10);
Odd od = new Odd(no, 10);
Thread oddThraed = new Thread(od, "ODD");
oddThraed.start();
Thread evenThraed = new Thread(ev, "Even");
evenThraed.start();
}
}
class TestNumber {
int no;
boolean flag = false;
public synchronized int getEvenNo() {
System.out.println("In Even Method");
// wait block so no other thread can enter on same object synchronized
// method
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = false;
notify();
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (!flag) {
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
public synchronized int getOddNo() {
System.out.println("In ODD Method");
no = no + 1;
System.out.println(Thread.currentThread().getName() + ":" + no);
flag = true;
notify();
// wait block so no other thread can enter on same object synchronized
// method
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
if (flag) {
try {
wait();
} catch (Exception e) {
// TODO: handle exception
}
}
return no;
}
}
class Even implements Runnable {
TestNumber num;
int noOfTime;
Even(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getEvenNo();
}
}
}
class Odd implements Runnable {
TestNumber num;
int noOfTime;
Odd(TestNumber no, int noOfTime) {
this.num = no;
this.noOfTime = noOfTime;
}
public void run() {
for (int i = 0; i < noOfTime; i++) {
num.getOddNo();
}
}
}
Note : As suggested by #chiastic-security Number is already defined in JDK, I have renamed it to TestNumber in this code.
Output :
In ODD Method
ODD:1
In Even Method
Even:2
In ODD Method
ODD:3
In Even Method
Even:4
In ODD Method
ODD:5
In Even Method
Even:6
In ODD Method
ODD:7
In Even Method
Even:8
In ODD Method
ODD:9
In Even Method
Even:10
In ODD Method
ODD:11
In Even Method
Even:12
In ODD Method
ODD:13
In Even Method
Even:14
In ODD Method
ODD:15
In Even Method
Even:16
In ODD Method
ODD:17
In Even Method
Even:18
In ODD Method
ODD:19
In Even Method
Even:20

How to stop the printing in thread A from thread B?

I have written some Java code, which will call a C interrupt handler.
In Java thread A, I use waitFor() to wait the interrupt coming and then execute reboot.
In Java thread B, I will loop printing a counter value and sleep several milliseconds.
And I hope when I detect the interrupt, and then stop the printing in thread B at once, but failed. In fact, the system detects the interrupt in time, but the printing continues for maybe 10 seconds and then reboot. Note: reboot occurs maybe 11 seconds after the interrupt(press a button), the hardware is not fast.
Below is my code, any suggestion? Thanks!
import java.io.IOException;
class ThreadTesterA implements Runnable
{
private int counter;
private String cmds[] = new String[1];
private Process pcs;
#Override
public void run()
{
cmds[0] = "./gpio-interrupt";
try {
pcs = Runtime.getRuntime().exec(cmds);
if(pcs.waitFor() != 0) {
System.out.println("error");
} else {
ThreadTesterB.setClosed(true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ThreadTesterB implements Runnable
{
private int i;
private static boolean closed=false;
public static void setClosed(boolean closed)
{
closed = closed;
}
#Override
public void run()
{
// replace it with what you need to do
while (!closed) {
System.out.println("i = " + i);
i++;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
public class ThreadTester
{
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(new ThreadTesterA());
Thread t2 = new Thread(new ThreadTesterB());
t1.start();
t1.setPriority(Thread.MAX_PRIORITY);
//t1.join(); // wait t1 to be finished
t2.start();
//t2.join();
}
}
You're writing and reading a boolean variable (closed) from 2 different threads without any kind of synchronization. There is thus no guarantee that what you wrote in one thread is visible in the other thread. You need to either
make the boolean variable volatile
access the boolean variable (writing and reading) using blocks or methods synchronized on the same lock
use an AtomicBoolean instead of a boolean
I would use the third solution.

Java thread lock when trying to lock/unlock with ReetrantLock(true)

I am having some trouble with a ReetrantLock(true) in an application that checks the difference between two images and shows similarity based on a percentage.
For some reason my input thread for reading in the minimum percent for being "similar" calls lock.lock() and that particular thread just deadlocks indefinitely but I can't seem to figure out why only that thread is deadlocking.
In the SSCCE below in the main method main(String[]) the inline Thread is used to get input from the console and if I type any number in it correctly stores it but as soon as it calls lock.lock() it deadlocks indefinitely and I am unsure why because the ReetrantLock has been told to be fair to caller threads and try to order them for when they called.
private static volatile boolean running = false;
public static void main(String[] args)
{
webcam2 webcam = new webcam2();
webcam.start();
(new Thread(new Runnable()
{
#Override
public void run()
{
Scanner scanner = new Scanner(System.in);
while (running)
{
System.out.print("Enter Double: ");
double val = scanner.nextDouble();
lock.lock(); // locks indefinatly here
if (val < 0.0D) reset = true;
dif = val;
System.out.println("Searching for value: " + dif);
lock.unlock();
}
scanner.close();
}
})).start();
}
private static double dif = 0.0D;
private static boolean reset = false;
private static ReentrantLock lock = new ReentrantLock(true);
#Override
public void run()
{
try
{
while (running)
{
// show image on window
lock.lock();
if (reset == true)
{
reset = false;
lock.unlock();
doComplexStuffToImage();
}
lock.lock();
doComplexStuffToImage();
lock.unlock();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void doComplexStuffToImage()
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
//swallow exception
}
}
public void start()
{
new Thread(this).start();
running = true;
}
public void stop()
{
running = false;
}
One thread is locking the ReentrantLock and not releasing it. What "reentrant" means is you can call lock many times, but you must call unlock() the same number of times. You lock twice, and unlock once so you are not actually unlocking the lock, thus no other process gets a chance.

IllegalMonitorStateException notify() and wait() [duplicate]

This question already has answers here:
Java Wait and Notify: IllegalMonitorStateException
(2 answers)
Closed 5 years ago.
I have a problem. When I use notify() in a synchronized block I get IllegalMonitorStateException. Can anyone help me solve this problem?
I need one thread to send a char to a second thread, then this thread has to wait and second thread print this char. After that second thread wait, and first one again sends next char
Main.java:
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
public class Main extends JFrame {
Thread t1, t2;
Consumer con;
public Main() {
con = new Consumer();
startThreads();
}
private synchronized void startThreads() {
t1 = new Thread(new Producent("grudzien", con));
t1.start();
t2 = new Thread(con);
t2.start();
}
public class Producent implements Runnable {
String m_atom;
char[] atoms;
Consumer m_c;
public Producent(String atom, Consumer c) {
m_atom = atom;
m_c = c;
}
#Override
public void run() {
synchronized (this) {
atoms = m_atom.toCharArray();
System.out.print("Tablica znaków: ");
for (int i = 0; i < atoms.length; i++) {
System.out.print(atoms[i] + ", ");
}
}
for (int i = 0; i < atoms.length; i++) {
synchronized (this) {
con.setChar(atoms[i]);
t2.notify();
try {
wait();
} catch (InterruptedException ex) {
JOptionPane.showMessageDialog(null, "Blad w wait()", "Blad!", JOptionPane.ERROR_MESSAGE);
}
}
}
}
}
public class Consumer implements Runnable {
char atom;
public void setChar(char c) {
atom = c;
}
#Override
public void run() {
while (true) {
synchronized (this) {
try {
wait();
} catch (InterruptedException ex) {
JOptionPane.showMessageDialog(null, "Blad w wait()", "Blad!", JOptionPane.ERROR_MESSAGE);
}
System.out.println(atom);
t1.notify();
}
}
}
}
public static void main(String[] args) {
new Main();
}
}
you need to be the "owner of the object's monitor" to be able to call notify on it. so far your methods are all synchronized(this), yet they call notify() on other objects (that they are not synchronized on). in other words:
synchronized(t2) {
t2.notify();
}
and
synchronized(t1) {
t1.notify();
}
for a complete explanation of monitors and synchronization in java, see here, or look for similar questions here on SO, like this one - Java Wait and Notify: IllegalMonitorStateException

Categories

Resources