Two threads accessing same variable lock application - java

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.

Related

Trying to Get Guarded Blocks to Work

I'm not understanding why my code is not working correctly. I expect the first Thread to wait for 4 seconds for the second Thread to set a shared boolean "joy" to true, then for the first Thread to print out "Joy has been achieved!".
When I run the code, I get this output:
"No Joy Yet..."
"Notifying Joy"
Then it freezes up and doesn't continue. If my understanding is correct, the notifyAll() method which is called from my notifyJoy() method should wake t1 up from its wait() and then, since the shared static boolean variable joy is now true, "Joy has been achieved!" should print to the console.
I'm working from Oracle's "The Java Tutorial", Chapter 13: here is a link to the specific section: Java Tutorial Website. I'm going off of what they have and making a little example but I can't seem to figure out what I'm doing wrong. Any help would be appreciated. Here is a complete copy of my code for your reference:
public class JoyTime {
public static void main(String[] args) {
JoyRider j1 = new JoyRider(false);
JoyRider j2 = new JoyRider(true);
Thread t1 = new Thread(j1, "J1");
Thread t2 = new Thread(j2, "J2");
t1.start();
try {
Thread.sleep(4000);
}
catch (InterruptedException e) {}
t2.start();
}
}
class JoyRider implements Runnable {
private static boolean joy = false;
private boolean flag;
public JoyRider(boolean flag) {
this.flag = flag;
}
#Override
public void run() {
synchronized(this) {
if (flag) {
notifyJoy();
}
else {
while (!joy) {
System.out.println("No Joy Yet...");
try {
this.wait();
}
catch (InterruptedException e) {}
}
System.out.println("Joy has been achieved!");
}
}
}
public synchronized void notifyJoy() {
System.out.println("Notifying Joy");
joy = true;
notifyAll();
}
}
You are calling wait() and notifyAll() on different monitors, and more specifically on the built-in monitors of the two different JoyRider instances.
If you introduce a dedicated lock object:
private static final Object LOCK = new Object();
and change your run() method a little:
synchronized (LOCK) {
if (flag) {
System.out.println("Notifying Joy");
JOY = true;
LOCK.notifyAll();
}
else {
while (!JOY) {
System.out.println("No Joy Yet...");
try {
LOCK.wait();
}
catch (InterruptedException e) {}
}
System.out.println("Joy has been achieved!");
}
}
you should be able to see all the expected prints in the correct order.

Make even and odd threads to print numbers in natural order in Java

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.

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.

Various way to stop a thread - which is the correct way

I had came across different suggestion of stopping a thread. May I know, which is the correct way? Or it depends?
Using Thread Variable http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Using boolean flag
private volatile boolean flag;
public void stop() {
flag = false;
}
public void run() {
while (flag) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
Using Thread Variable together with interrupt
private volatile Thread blinker;
public void stop() {
blinker.interrupt();
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (!thisThread.isInterrupted() && blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
None of these is the "correct" way, they're all valid. Which one you use depends on your circumstances, and which one works best for you.
As long as you don't use Thread.stop(), and you tidy up any resources left open by your threads (connections, temp files, etc), then it doesn't really matter how you go about it.
I always use the boolean flag - its the simplest.
Its really short and easy to understand for reviewers, but it has the handycap that you can't interrupt the sleep call. You should only use the interrupt variants for time-critical thread stopping. And, like skaffman said - Don't use Thread.stop()!
what about this
class Tester {
public static void main() {
Try t = new Try();
Thread.sleep(10); //wait for 10 milliseconds
t.interrupt(); // 'interrupt' i.e stop the thread
}
}
public class Try extends Thread {
#override
public void interrupt() {
//perform all cleanup code here
this.stop();
/*stop() is unsafe .but if we peform all cleanup code above it should be okay ???. since thread is calling stop itself?? */
}
}

Categories

Resources