I would like to say that I tried to find some answers on this site but I couldn't manage, also this is my first question so I am sorry if i wrote it off format etc...
I am trying to learn java and now trying to understand thread section. So far I understood some basics and I wanted to try this: a lieutenant class shares the monitor-lock with a soldier class but I am failing at somewhere.
Edit: I want to Lieutenant waits until the Soldier says his first line, then he gives an order. But when soldier tries to release lock I get an monitor error because of notify method.
"Exception in thread "Thread-1" java.lang.IllegalMonitorStateException."
P.S: I know there are easier ways but I am trying to utilize wait¬ify.
public class Lieutenant {
private boolean waitForCommand = true;
public void setWaitForCommand(boolean waitForCommand) {
this.waitForCommand = waitForCommand;
}
public synchronized void giveOrder() {
while (waitForCommand) {
try {
wait();
} catch (InterruptedException e) {
e.getStackTrace();
}
System.out.println("I said run soldier! RUN!");
}}}
public class Soldier {
private final Lieutenant lieutenant;
public Soldier(Lieutenant lieutenant) {
this.lieutenant = lieutenant;
}
public void getOrder() {
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}}
class Main {
public static void main(String[] args) {
Lieutenant lieutenant = new Lieutenant();
Soldier soldier = new Soldier(lieutenant);
new Thread(new Runnable() {
#Override
public void run() {
lieutenant.giveOrder();
}}).start();
new Thread(new Runnable() {
#Override
public void run() {
soldier.getOrder();
}}).start();
}}
The immediate problem here is with this method:
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}
The synchronized block is holding a lock on this.lieutenant but you are attempting to call notifyAll() on this, which you aren't holding the lock on.
If make this change
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
this.lieutenant.notifyAll();
}}
It should work better. But as mentioned in the comments you can't guarantee that giveOrder will be called before getOrder.
Related
I have a Thread and I need to set when it is listening or in standby, for that I've defined
public static enum ListenerState { STAND_BY, LISTENING };
and a method
public void setState(ListenerState state){
this.state = state;
}
now, in the main loop I check the state in this way
#Override
public void run() {
while (!Thread.interrupted()) {
try {
if (state==ListenerState.LISTENING){
// do my job
}
else{
Thread.sleep(300);
}
}
}
}
Is this approach thread-safe ?
No, do like that:
class MyThread implements Runnable {
private volatile ListenerState state;
public synchronized void setState(ListenerState state){
this.state = state;
}
#Override
public void run() {
while (true) {
try {
if (state==ListenerState.LISTENING){
// do my job
} else{
Thread.sleep(300);
}
} catch (IterruptedException ex){
return;
}
}
}
}
You can find your answer here: Do I need to add some locks or synchronization if there is only one thread writing and several threads reading?
in one word: better to add volatile keyword to state.
if state can be changed or read by different thread, then you need to synronize block for reading and writing methods. or as a better way, use AtomicBoolean. it is perfect object to get rid of syncronize block and make it thread safe
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html
I have two threads and in one thread I set static variable and in another I check static variable via function like this
Test test= new Test();
while(!Temp.isVarSet()){
}
System.out.println("Variable set");
But this codes hangs - doesn't go to println statement. But the following code works
Test test= new Test();
while(!Temp.isVarSet()){
System.out.println("I am still here");
}
System.out.println("Variable set");
The Temp class
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public synchronized static boolean isVarSet() {
return Temp.varSet;
}
}
Test class
public class Test{
public Test() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Model model= new Model();
View view = new View();
Controller controller=new Controller(model, view);
Temp.setVarSet();
...
}
});
}
}
What can be reason? I set method isVarSet() synchronized but it didn't help.
EDIT
This code works too.
Test test = Test()
while(!Temp.isVarSet()){
Thread.sleep(100);
}
You didn't publish what happens in Temp and isVarSet but most probably you change a variable. This variable must be marked volatile.
If your class looks like this:
public class Temp {
private static boolean someFlag;
public static boolean isVarSet() {
return someFlag;
}
}
And your loop is the same as the example, the compiler thinks that there's no need to read the flag over and over again because the flag is not changed inside the loop and it optimizes to not read the flag over and over.
Marking someFlag as volatile:
private static volatile boolean someFlag;
Will force the runtime to check the flag on each iteration and not just assume that the value hasn't changed. In this case, it will work.
From Oracle docs about atomic access:
Atomic actions cannot be interleaved, so they can be used without fear
of thread interference. However, this does not eliminate all need to
synchronize atomic actions, because memory consistency errors are
still possible. Using volatile variables reduces the risk of memory
consistency errors, because any write to a volatile variable
establishes a happens-before relationship with subsequent reads of
that same variable. This means that changes to a volatile variable are
always visible to other threads. What's more, it also means that when
a thread reads a volatile variable, it sees not just the latest change
to the volatile, but also the side effects of the code that led up the
change.
Even after you made variable as volatile .
if you add SOP in while loop it is working
These two usecase gives me another thought. just try it.
Since your read and write methods are sync , in your while loop
while(!Temp.isVarSet()){
}
It is nothing doing other than calling the method, it may possible this sync method holds the lock on the Temp Object which does not allow other thread to modify the values (though sync setMethod) .
While add SOP inside the while , it is doing some work on IO and thus it is allowing some time slice to other thread get the lock of Temp and modify the same.
Could you please try remove Sync from read method , just for testing purpose and post your results.
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
This works perfect for me:
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread t1 = new TheThread();
t1.start();
// wait
Thread.sleep(500);
System.out.println(Thread.currentThread().getId() + " will now setVarSet()");
Temp.setVarSet();
System.out.println(Thread.currentThread().getId() + " setVarSet() setted");
t1.join();
System.out.println(Thread.currentThread().getId() + " end programm");
}
private static class TheThread extends Thread {
#Override
public void run() {
System.out.println(Thread.currentThread().getId() + " enter run");
while (!Temp.isVarSet()) {
System.out.println(Thread.currentThread().getId() + " running");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
// ignore
}
}
System.out.println(Thread.currentThread().getId() + " exit run");
}
}
private static class Temp {
private volatile static boolean varSet = false;
public static void setVarSet() {
Temp.varSet = true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
}
Can you please post a complete example?
Its working as expected without hanging the program.
private volatile static boolean varSet = false;
public synchronized static void setVarSet() {
varSet = true;
}
public synchronized static boolean isVarSet() {
return varSet;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!TestDemo.isVarSet()) {
// System.out.println("I am still here");
}
System.out.println("Variable set");
}
});
t1.start();
Thread.sleep(1000); // put delay to give the chance to execute above thread
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Model model= new Model();
// View view = new View();
// Controller controller=new Controller(model, view);
setVarSet();
}
});
}
OK, So I have these classes that extend Thread, what I'm supposed to do is:
Let all alumns arrive.
When alumns arrive they say 'Hi'.
If the teacher arrives but not all of the Alumns have arrived then he should wait() for them.
Alumns should notify() the teacher when they're all there.
An alumn is a Thread initialized with boolean value 0.
A teacher is a Thread initialized with boolean value 1.
Person/Greeting Code
public class Person extends Thread {
private Thread t;
private String threadName;
boolean id;
Greeting greeting;
public Person(String name,boolean tipo,int n){
this.threadName = name;
this.id=tipo;
greeting =new Greeting();
}
#Override
public void run() {
if(id==false) {
try {
greeting.alumn(threadName);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
else{
try {
greeting.teacher(threadName);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public void start()
{
System.out.println("Starting "+ threadName);
if(t==null)
{
t=new Thread(this,threadName);
t.start();
}
}
}
class Greeting {
public void alumn(String s) throws InterruptedException{
System.out.println(s);
synchronized (this){
System.out.println("Alumn: "+s);
notifyAll();
}
}
public synchronized void teacher(String s) throws InterruptedException {
wait();
System.out.println(s);
}
}
Main class
public class ClassRoom {
public static void main(String [] args) {
Person francisco = new Person("Francisco",false,1);
Person jesus = new Person("Jesus", false,2);
Person alberto = new Person("Alberto",false,3);
Person karla = new Person("Karla",false,4);
Person maestro = new Person("Professor",true,0);
francisco.start();
jesus.start();
alberto.start();
karla.start();
maestro.start();
}
}
The problem:
If the teacher arrives first he goes to wait()...then alumns arrive but he never wakes up.
If the teacher doesn't arrive first, he still never wakes up!
How to fix this?
If the teacher arrives first he goes to wait()...then alumns arrive
but he never wakes up.
All you Persons instantiate their own Greeting, which synchronzizes on this and therefore also waits/notifies on this. Each Person uses its own semaphore, which is not what you want. You should synchronize on the same object (perhaps Greeting.class) for all instances.
If the teacher doesn't arrive first, he still never wakes up! How to fix this?
Simply check if all alumns are there. If yes greet, else wait for notify. Afterwards check again. The check has to be part of the synchronized block to avoid race conditions.
To wait until all threads has arrived to certain point, consider using CyclicBarrier.
I wrote a simple class that uses AbstractQueuedSynchronizer. I wrote a class that represents a "Gate", that can be passed if open, or is blocking if closed. Here is the code:
public class GateBlocking {
final class Sync extends AbstractQueuedSynchronizer {
public Sync() {
setState(0);
}
#Override
protected int tryAcquireShared(int ignored) {
return getState() == 1 ? 1 : -1;
}
public void reset(int newState) {
setState(newState);
}
};
private Sync sync = new Sync();
public void open() {
sync.reset(1);
}
public void close() {
sync.reset(0);
}
public void pass() throws InterruptedException {
sync.acquireShared(1);
}
};
Unfortunately, if a thread blocks on pass method because gate is closed and some other thread opens the gate in meantime, the blocked one doesn't get interrupted - It blocks infinitely.
Here is a test that shows it:
public class GateBlockingTest {
#Test
public void parallelPassClosedAndOpenGate() throws Exception{
final GateBlocking g = new GateBlocking();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
g.open();
} catch (InterruptedException e) {
}
}
});
t.start();
g.pass();
}
}
Please help, what should I change to make the gate passing thread acquire the lock successfully.
It looks like setState() only changes the state, but doesn't notify blocked threads about the change.
Therefore you should use acquire/release methods instead:
#Override
protected boolean tryReleaseShared(int ignored) {
setState(1);
return true;
}
...
public void open() {
sync.releaseShared(1);
}
So, overall workflow of AbstractQueuedSynchronizer looks like follows:
Clients call public acquire/release methods
These methods arrange all synchronization functionality and delegate actual locking policy to protected try*() methods
You define your locking policy in protected try*() methods using getState()/setState()/compareAndSetState()
Can someone please help me out.
I need to use two threads in a way that one thread will run permanently while(true) and will keep track of a positioning pointer (some random value coming in form a method). This thread has a logic, if the value equals something, it should start the new thread. And if the value does not equal it should stop the other thread.
Can someone give me some code snippet (block level) about how to realize this?
Create a class that implements Runnable. There you'll make a run() method.
Like:
public class StackOverflow implements Runnable{
private Thread t = null;
public void run(){
}
public void setAnotherThread(Thread t){
this.t = t;
}
}
On the main class, you'll create 2 instances of Thread based on the other class you created.
StackOverflow so1 = new StackOverflow();
StackOverflow so2 = new StackOverflow();
Thread t1 = new Thread(so1);
Thread t2 = new Thread(so2)
Then you set one thread in the other, so you can control it.
t1.setAnotherThread(so2);
t2.setAnotherThread(so1);
Then you do what you need to do.
Ok if I'm not mistaken, you want to have one class that could be run as a "Thread" or as a (lets call it) a "sub-Thread".
But how to do that with one run method? just declare a boolean variable that specifies whether the thread object is a sub-thread or a parent thread, and accordingly declare two constructors, one would create a parent thread and the other would create a sub thread, and to be able to stop the sub-thread declare another variable called stop that is default to false.
class ThreadExample extends Thread {
private boolean sub = false;
private ThreadExample subThread = null;
public boolean stop = false;
public ThreadExample() {
}
public ThreadExample(boolean sub) {
this.sub = sub;
}
public void run() {
if (sub) {
runSubMethod();
} else {
runParentMethod();
}
}
public void runParentMethod() {
boolean running = true;
while (running) {
if (getRandomValue() == some_other_value) {
if (getSubThread().isAlive()) {
continue;
}
getSubThread().start();
} else {
getSubThread().makeStop();
}
}
}
public void runSubMethod(){
while(true){
//do stuff
if (stop)
break;
}
}
public int getRandomValue() {
//your "Random Value"
return 0;
}
private ThreadExample getSubThread() {
if (subThread == null) {
subThread = new ThreadExample(true);
}
return subThread;
}
public void makeStop(){
stop = true;
}
}
Here is a simple idea how you can implement as many threads as you like in a class:
class MultipleThreads{
Runnable r1 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//-----
Runnable r2 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//--- continue as much you like
public static void main (String[] args){
Thread thr1 = new Thread(r1);
Thread thr2 = new Thread(r2);
thr1.start();
thr2.start();
}
}
Hope it helps!!
For communicating between the two threads, one simple solution is to set a boolean type volatile static variable, and have it set from one thread and put it in while(flag) condition in the other thread.
You can control the other thread using this method.
And if you have waiting processes or Thread.sleep() and you want to break the thread without having it to finish it, your interrupts by catching the exception.