I was trying to implement a reader-writer using notify and wait. But i think I'm stuck.
My sequence goes like this.
RRRRRRRRRRWWWWWWWWW This happens if the main start with reader invoked first.
Or
WWWWWWWRRRRRRRRRRR. This happens if the main start with the writer invoked first.
Looks like reads notify isn't working at all. Writer thread never goes into execution.
If i make while loop in run method to run infinite then it's just
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR......... No chance for the writer to write.
Can you have a look at this?
DATA CLASS
public class Data {
private int q ;
private boolean isAnyOneReading;
public Data() {
}
public void readQ() {
synchronized (this){
isAnyOneReading = true;
System.out.println("Read start "+q);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this){
isAnyOneReading = false;
System.out.println("Read end "+q);
notifyAll();
}
}
public synchronized void writeQ(int q) {
System.out.println(isAnyOneReading);
while (isAnyOneReading){
try{
wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("Done");
Thread.currentThread().interrupt();
}
}
System.out.println("Write start "+q);
this.q = q;
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println("Write end "+q);
notifyAll();
}
}
READER CLASS
public class Reader implements Runnable {
private Data data;
private Thread readerThread;
public Reader(Data data) {
this.data = data;
readerThread = new Thread(this, "ReaderThread");
}
void startThread(){
readerThread.start();
}
#Override
public void run() {
int i = 0 ;
while (i != 5){
data.readQ();
i++;
}
}
}
WRITER CLASS
public class Writer implements Runnable{
private Data data;
private Thread writerThread;
public Writer(Data data) {
this.data = data;
writerThread = new Thread(this,"WriterThread," );
}
void startThread(){
writerThread.start();
}
#Override
public void run() {
int i = 0 ;
int j = 0 ;
while (j != 5){
data.writeQ(i++);
// i++;
j++;
}
}
}
MAIN CLASS
public class ReaderWriterDemo {
public static void main(String[] args) {
Data data = new Data();
Reader reader = new Reader(data);
Writer writer = new Writer(data);
reader.startThread();
writer.startThread();
}
}
Try removing the Thread.sleep from Data class.
And add Thread.sleep in run methods like so. (pasting one example):
#Override
public void run() {
int i = 0;
while (i != 5) {
data.readQ();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
i++;
}
}
}
Read's notifyAll() works, but it seems that read() re-called again and changes isAnyOneReading's value prior to any other action in write(). That's why check fails and write() starts waiting again. As Danny Fried suggested moving Thread.sleep() to the run methods will help.
Looks like a simple case of starvation. Consider your writer's main loop:
while (j != 5){
data.writeQ(i++);
// i++;
j++;
}
data.writeQ() is a synchronized method: The very last thing it does before it returns is to unlock the lock. The very first thing it does on the next call is to re-lock the lock. Not much happens in-between--increment and test a local variable is all.
Java synchronized locks are not fair. (i.e., when a lock becomes available, the system does not guarantee that the winner will be the thread that's been waiting the longest.) In fact, it may be be the opposite of fair: The OS may try to maximize efficient use of the CPU(s) by always choosing the thread that's easiest to wake up.
When the writer comes back to call data.writeQ() on each subsequent iteration, it may be that the OS has not even have started to wake up the reader, and it simply lets the writer enter the synchronized block again.
Same thing happens with your reader. The code is a bit more complicated, but just like in the writer, the very last thing that data.readQ() does before returning is to unlock the lock, and the very first thing that it does on the next call is to lock it again.
Brute force solution: replace the synchronized blocks with a fair ReentrantLock object.
Alternate solution, which is more typical of how many programs actually work: Have the threads do something else (e.g., have them do some I/O) in between calls to the locked function, thereby giving the other threads a chance to get in and use the locked resource.
Related
I am having troubles with stopping a thread which is started from outside the class using a actionPerformed on a JButton. Code of the thread class below.
public synchronized void run ()
{
try
{
do
{
int minuta = vrijeme / 60;
int sekundi = vrijeme % 60;
System.out.println(minuta+" "+sekundi);
vrijeme = vrijeme - 1;
delay = delay - 1000;
if (minuta == stani && sekundi == 0)
{
}
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
while (delay != 0);
{
//
}
}
catch (Exception e)
{
System.out.println("Stao" + e);
}
}
void pokreniThread()
{
(new Thread(new OdredenoVrijeme())).start();
}
synchronized public void zaustaviThread()
{
try
{
(new Thread(new OdredenoVrijeme())).wait();
}
catch (Exception e)
{
System.out.println("stao" +e);
}
}
}
Every time i call .sleep() .wait() or anything similar i get the following catch message:
java.lang.IllegalMonitorStateException
Under Java, you cannot have a sleep in the main process. Create a sub-thread, which will do the sleep, then post a message to a handler in the main-thread, to do something after the timeout.
If you want to stop a thread itself, set a variable inside the thread like is_stopping=true, then inside the thread you could set a variable is_running=false after the thread stops itself.
is_running=true;
while (is_running & !is_stopping)
{
do_something();
sleep();
}
is_stopping=false;
is_running=false;
In java the main thread is playing a scheduler part in the program. So in a multithreading situation you have these parts:
scheduler/controller
provider
customer
The main thread should always play the scheduler/controller part of the program. BTW you are not using multithreading in a good way. use synchronized when its absolutely necessary.
look at the following code. you should use synchronization like this:
public class BlockingQueue<T> {
private Queue<T> queue = new LinkedList<T>();
private int capacity;
public BlockingQueue(int capacity) {
this.capacity = capacity;
}
public synchronized void put(T element) throws InterruptedException {
while(queue.size() == capacity) {
wait();
}
queue.add(element);
notify(); // notifyAll() for multiple producer/consumer threads
}
public synchronized T take() throws InterruptedException {
while(queue.isEmpty()) {
wait();
}
T item = queue.remove();
notify(); // notifyAll() for multiple producer/consumer threads
return item;
}
You cannot stop a thread from an external context. The thread should stop itself when some condition changes.
You have to hold a flag in your thread that you want to stop, and the thread to check the flag in a loop. If the flag is changed, then the thread itself should do nothing and it will exit by itself
I know this question has been asked before, But I am unable to figure out why my solution is not working for me. I have two threads even and odd, one prints even numbers and other prints odd numbers. When I start the threads I want the output to be in natural order of numbers like 0 1 2 3..etc. This is my code:-
[updated]
public class ThreadCommunication {
public static void main(String... args) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread(){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
obj.notify();
}
}
}
};
even.start();
odd.start();
}
}
when I run the above code, sometimes it prints the numbers in natural order as expected but sometimes it prints in some other order for ex:
0
1
3
5
7
9
2
What am I doing wrong here?
Edit:
volatile static boolean isAlreadyWaiting = false;
Thread even = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 0; i < 10; i = i + 2) {
System.out.println(i);
try {
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
obj.notify();
isAlreadyWaiting=false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread() {
#Override
public void run() {
synchronized (obj) {
for (int i = 1; i < 10; i = i + 2) {
System.out.println(i);
try {
if(isAlreadyWaiting){
obj.notify();
isAlreadyWaiting = false;
}
if (!isAlreadyWaiting) {
isAlreadyWaiting = true;
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Check documentation
public class IllegalMonitorStateException extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's
monitor or to notify other threads waiting on an object's monitor
without owning the specified monitor.
Monitor is owned by obj
So you should call
obj.wait();
and
obj.notify();
For more info on Ownership
This methods (wait or notify) 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.
Only one thread at a time can own an object's monitor.
#Pragnani Kinnera is right about the exception you're seeing. But if you want to alternate between even and odd, you'll need to move your second synchronized block into the loop. Otherwise, the notifying thread will hold the lock exclusively until the loop completes. (As opposed to the first thread, which yields its lock on each round.)
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
synchronized(obj){
System.out.println(i);
notify();
}
}
}
};
The first thread, however, should have the loop inside the synchronized block. If both threads release the lock, they both have an equal chance at reacquiring it. But if the first loop is inside the synchronized block, the second thread won't be able to reenter until the first has completed a full round and is waiting once again.
EDIT: This still won't work correctly, because there is no guarantee that the first thread won't reacquire the lock before the second thread does, per this quote from the documentation:
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
You'll probably want to wake and notify from both threads to ensure they're in sync.
Here is your solution:
public class ThreadCommunication {
public static void main(String args[]) throws InterruptedException
{
final ThreadCommunication obj = new ThreadCommunication();
Thread even = new Thread("Even Thread"){
#Override
public void run()
{
for(int i=0;i<10;i=i+2){
System.out.println(i);
synchronized(obj){
obj.notify();
}
synchronized(obj){
try {
obj.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
Thread odd = new Thread(){
#Override
public void run()
{
for(int i=1;i<10;i=i+2){
try {
synchronized(obj){
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
synchronized(obj){
obj.notifyAll();
}
}
}
};
even.start();
odd.start();
}
}
As explained by #shmosel, your synchronized block should only contain code that need to be synchronized.
I am trying to simulate a parking lot entry system that contains 2 floors of 20 spaces and 2 entries and 2 exits. I am using Threads in Java, and I have tried to use thread.wait() and thread.sleep but they don't help in making a thread run after another thread is over.
This is what I have come up with so far:
ShardedDataThread.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SharedDataThread extends Thread {
private SharedData mySharedData;
private String myThreadName;
public int L1 = 20;
public int L2 = 20;
//Setup the thread
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
SharedDataThread(String name, SharedData sharedstuff) {
super(name);
mySharedData=sharedstuff;
myThreadName=name;
}
//This is called when "start" is used in the calling method
public void run() {
while(true){
System.out.println("Entry or Exit?");
String input = null;
try {
input = br.readLine();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (input.equalsIgnoreCase("entry")) {
try {
// Acquire the lock using the acquireLock() method
// The thread will pause here on wait() until it gets a lock
mySharedData.acquireLock();
//use park method to occupy one space
this.park(); // Increment the number of reads
mySharedData.releaseLock();
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when reading:"+e);
}
}
else {
try {
mySharedData.acquireLock();
System.out.println(myThreadName+" is writing");
exit(); // INCREMENT ONE SPOT
mySharedData.releaseLock(); // releases the lock
}
catch(InterruptedException e) {
System.err.println("Failed to get lock when writing:"+e);
}
}
System.out.println("L1 has : "+L1+" "+"L2 has: "+" "+L2);
}
//while ends
}
//State method
public void park() {
if (L1>0 && L1<=20){
L1= L1-1;
}
else if (L1==0 && L2<=20 && L2>0){
L2= L2-1;
}
else if (L1==0 && L2==0){
System.out.println("No Spaces Left");
}
}
public void exit() {
if (L1<20) {
L1 = L1 +1;
} else if (L2<20) {
L2 = L2+1;
}
}
public static void main(String[] args) throws InterruptedException {
SharedData mySharedData = new SharedData();
SharedDataThread myThread1 = new SharedDataThread("Entry1", mySharedData);
//SharedDataThread myThread2 = new SharedDataThread("Entry2", mySharedData);
//SharedDataThread myThread3 = new SharedDataThread("Exit1", mySharedData);
//SharedDataThread myThread4 = new SharedDataThread("Exit2", mySharedData);
// Now start the threads executing
myThread1.start();
//myThread1.join();
//myThread2.start();
//myThread2.join();
//myThread3.start();
//myThread3.join();
//myThread4.wait();
}
}
SharedData.java
public class SharedData {
private boolean accessing=false; // true a thread has a lock, false otherwise
// attempt to acquire a lock
public synchronized void acquireLock() throws InterruptedException{
Thread me = Thread.currentThread();
while (accessing) {
wait();
}
accessing = true;
}
// Releases a lock to when a thread is finished
public synchronized void releaseLock() {
//release the lock and tell everyone
accessing = false;
notifyAll();
Thread me = Thread.currentThread(); // get a ref to the current thread
}
}
This never makes any sense:
myThread1.start();
myThread1.join();
It never makes any sense to start a thread and then immediately wait for it to finish. The entire point of having threads is that different threads can be doing different things at the same time.
If there isn't anything else that the caller wants to do while myThread1 is running, then there is no reason to create myThread1. The caller should just do whatever it is that myThread1 would have done at that point.
Don't use threads to model objects in a simulation. Use threads to do work. Usually, that means, use a thread pool such as java.util.concurrent.ThreadPoolExecutor to perform tasks.
If you want your simulation to run in real time, don't use threads that sleep(). Use a scheduler such as java.util.concurrent.ScheduledThreadPoolExecutor to perform delayed tasks.
You're thinking about the problem wrong. Don't think about waiting for a thread to do something after a thread is done. Think about doing something after some work is done. That means that the work has to be waitable.
The following code was summed up the application, the application randomly was locked in
while (flag)
This code, running on my machine gets caught, in another machine he finished normally
The output generated here is:
INIT
END
before while
before flag
after flag
Code:
package threads;
public class Run implements Runnable {
private Thread thread;
private boolean flag = true;
public void init() {
thread = new Thread(this);
thread.setName("MyThread");
thread.start();
}
#Override
public void run() {
try {
int i = 0;
while (i < 1000) {
i++;
}
System.out.println("before flag");
flag = false;
System.out.println("after flag");
} catch (Exception e) {
e.printStackTrace();
} finally {
flag = false;
}
}
public void end() {
thread.interrupt();
thread = null;
System.out.println("before while");
while (flag) {
// try { Thread.sleep(100);} catch (InterruptedException e) {}
}
;
System.out.println("after while");
}
public static void main(String[] args) {
Run r = new Run();
System.out.println("INIT");
r.init();
System.out.println("END");
r.end();
}
}
Why when I change the value of flag the main thread does not pass through loop?
Change
private boolean flag = true;
to
private volatile boolean flag = true;
Without volatile, there is no guarantee the waiting thread needs to see the value get updated. HotSpot might even inline while(flag) to while(true) if the loop spins enough times.
See Memory Consistency Errors.
Also, what you're doing is called a spinlock. Normally you should use thread.join() instead. A spinlock is wasteful of resources because the waiting thread is actually working (checking a variable) the entire time it is supposed to be waiting.
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.