I'd use a volatile condition variable, but I think volatile is redundant. Besides I'm not quite sure I understood this point from https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility correctly:
An unlock (synchronized block or method exit) of a monitor
happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Here is a sample app.
package sample;
public class Foo {
private boolean shouldWait;
private final Object lock = new Object();
void blockThread() {
synchronized (lock) {
shouldWait = true;
while (shouldWait) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
void notifyThread() {
synchronized (lock) {
shouldWait = false;
lock.notify();
}
}
}
Test.
package sample;
public class Main {
private static Foo foo = new Foo();
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
foo.blockThread();
}
}).start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
new Thread(new Runnable() {
#Override
public void run() {
foo.notifyThread();
}
}).start();
}
}
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Yes. volatile writes have the same relationship. All actions prior to a volatile write happens-before all subsequent reads.
Related
look the java wait/notify code. I think, will not print false.
But, when I run the code, print false somtime.
Is it java bug?
public class TestThread {
public static volatile String lock = "111";
public static volatile AtomicBoolean flag = new AtomicBoolean(true);
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
try {
while (true) {
synchronized (lock) {
flag.compareAndSet(true, false);
lock.wait();
if (!flag.get()) {
System.out.println(flag.get());
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
flag.compareAndSet(false, true);
lock.notify();
}
}
}
}).start();
}
}
console result:
false
false
false
The reason for such a behavior is called spurious wakeup.
Thread may stop waiting and continue it's execution without notify() call. This is a spurious wakeup - a mechanism of operation system thread scheduler.
That's why you always check some condition before calling wait() and set it explicitly before calling notify(). Do not use notify() itself as a guarantee of a job being done.
Example:
Thread 1
synchronized (lock) {
...
while (!condition) {
lock.wait();
}
...
}
Thread 2
synchronized (lock) {
condition = true;
lock.notify();
}
public class Test2 {
static int count;
public static void main(String[] args) {
final Test2 t1 = new Test2();
final Test2 t2 = new Test2();
new Thread(new Runnable() {
#Override
public void run() {
t1.foo();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
t1.bar();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
t2.foo();
}
}).start();
}
public static synchronized void foo() {
synchronized (Test2.class) {
System.out.println("run bar"+count++);
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static synchronized void bar() {
System.out.println("run bar");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
above are codes which I tried.When I write all codes in one Class synchronized (Test2.class) and I found something strange happened.After I invoked foo() method I can't invoke bar() method immediately. what I think it lock same object.how to explain this strange thing.
All 3 of the threads your code starts acquire the same lock, on the Test2 class. When you write a method starting with
static synchronized
that means it has to acquire the lock on the class object.
The synchronized block in the foo method is redundant. It specifies using the same class to lock on as using static synchronized. Since intrinsic locks are reentrant this doesn't cause a problem.
Anyway, each of your threads acquires the lock, runs to completion, then releases the lock. Since you are locking on the class and not on an instance it doesn't matter which instance of Test2 your threads use, they still acquire the same lock and execute one at a time.
When I ran this I got the following output:
c:\Users\ndh>java Test2
run bar0
run bar1
run bar
The order in which these threads run is up to the scheduler. It would seem reasonable to guess that the Runnable calling t1.foo got a head start -- since it was created and started first it's likely to have a window where it won't have any competition acquiring the lock.
Please refer to the code below
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
method2();
}
}
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
As per my understanding, the code in method2 should not be executed in any case, since method1 holds the lock on Integer.class and method2 tries to access the lock on Integer.class again. But to my surprise, the code runs fine and it prints "hi there" to the console. Can someone clarify?
Locks are owned by threads. If your thread already owns a lock, Java assumes that you don't need to acquire it a second time and just continues.
You'll get a deadlock if you start a second thread in method1() while holding the lock and the second thread executes the method method2().
If you prefer code, then synchronized works like this:
Lock lock = Integer.class.getLock();
boolean acquired = false;
try {
if(lock.owner != Thread.currentThread()) {
lock.acquire();
acquired = true;
}
...code inside of synchronized block...
} finally {
if(acquired) lock.release();
}
Here is code to demonstrate the deadlock. Just set runInThread to true:
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
boolean runInThread = false;
if( runInThread ) {
Thread t = new Thread() {
#Override
public void run() {
method2();
}
};
t.start();
try {
t.join(); // this never returns
} catch( InterruptedException e ) {
e.printStackTrace();
}
} else {
method2();
}
}
}
private void method2() {
System.out.println("trying to lock");
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
It seems you have misunderstood the concept.
A method never acquires a lock, the instance on which the method is invoked serves as a lock in case of synchronized method and in case of synced block the thread acquires the lock on specified object.
Here the instance acquires the lock on Integer.class and then it goes on to execute method2.
There is no case of deadlock as in your case thread continues for the execution of the method that you're calling inside method1. So there is no deadlock that happens.
your code is equivalent to:
synchronized (Integer.class) {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
if the thread acquired the lock and entered the first synchronized block it will have no problem accessing the 2nd
to produce a deadlock the call to method2 should be executed by a different thread.
synchronized (Integer.class) {
method2();
}
when you calling this method2(); then its not giving lock to any kind of mehtod its continues goes to the method that you are calling means this.
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
and after completing its returning. so there is no case of dead lock. hope this explanation helps.
As already said, one thread can access more than one synchronised blocks when no other thread already blocks it. In that situation the same thread can reenter synchronised block because it already holds it from method1.
To cause the deadlock you have to use two thread at least and two different locks. It have to access two locks in the reverse order. Check out that code:
private void method1() throws InterruptedException
{
synchronized (Integer.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 1");
Thread.sleep(1000);
method2();
}
}
private void method2() throws InterruptedException
{
synchronized (Double.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 2");
Thread.sleep(1000);
method1();
}
}
public static void main(String[] args) throws InterruptedException
{
new Thread()
{
#Override
public void run()
{
try
{
new DeadLock().method1();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}.start();
new DeadLock().method2();
}
I was reading this post and the suggestions given to interrupt one thread from another is
" " " Here are a couple of approaches that should work, if implemented correctly.
You could have both threads regularly check some common flag variable (e.g. call it stopNow), and arrange that both threads set it when they finish. (The flag variable needs to be volatile ... or properly synchronized.)
You could have both threads regularly call the Thread.isInterrupted() method to see if it has been interrupted. Then each thread needs to call Thread.interrupt() on the other one when it finishes." " "
I do not understand how the second approach is possible that is using Thread.isInterrupted().
That is, how can Thread-1 call Thread.interrupt() on Thread-2.
Consider this example, in the main method I start two threads t1 and t2. I want t1 to stop t2 after reaching certain condition. how can I achieve this?
class Thread1 extends Thread {
public void run(){
while (!isDone){
// do something
}
} //now interrupt Thread-2
}
class Thread2 extends Thread {
public void run(){
try {
while(!Thread.isInterupted()){
//do something;
}
catch (InterruptedExecption e){
//do something
}
}
}
public class test {
public static void main(String[] args){
try {
Thread1 t1 = new Thread1();
Thread2 t2 = new Thread2();
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The context of this is that you are trying to implement your scheme using thread interrupts.
In order for that to happen, the t1 object needs the reference to the t2 thread object, and then it simply calls t2.interrupt().
There are a variety of ways that t1 could get the reference to t2.
It could be passed as a constructor parameter. (You would need to instantiate Thread2 before Thread1 ...)
It could be set by calling a setter on Thread1.
It could be retrieved from a static variable or array, or a singleton "registry" object of some kind.
It could be found by enumerating all of the threads in the ThreadGroup looking for one that matches t2's name.
public class test {
private static boolean someCondition = true;
public static void main(String[]args){
Thread t2 = new Thread(new someOtherClass("Hello World"));
Thread t1 = new Thread(new someClass(t2));
t2.start();
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class someClass implements Runnable{
Thread stop;
public someClass(Thread toStop){
stop = toStop;
}
public void run(){
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(someCondition && !stop.isInterrupted()){
stop.interrupt();
}
}
}
}
static class someOtherClass implements Runnable{
String messageToPrint;
public someOtherClass(String s){
messageToPrint = s;
}
public void run(){
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(messageToPrint);
}
}
}
}
You could consider the use of Future interface. It provides a cancel() method.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
Playing with interruption makes your life unnecessarily hard. Besides the fact that your code must know the threads, interruption does not provide any context information about the reason of the interruption.
If you have a condition that is shared by your code possibly executed by different threads, just encapsulate that condition into an object and share that object:
public class Test {
public static void main(String[] args) {
Condition c=new Condition();
new Thread(new Setter(c)).start();
new Thread(new Getter(c, "getter 1")).start();
// you can simply extend it to more than one getter:
new Thread(new Getter(c, "getter 2")).start();
}
}
class Getter implements Runnable {
final Condition condition;
final String name;
Getter(Condition c, String n) { condition=c; name=n; }
public void run() {
while(!condition.isSatisfied()) {
System.out.println(name+" doing something else");
try { Thread.sleep(300); } catch(InterruptedException ex){}
}
System.out.println(name+" exiting");
}
}
class Setter implements Runnable {
final Condition condition;
Setter(Condition c) { condition=c; }
public void run() {
System.out.println("setter: doing my work");
try { Thread.sleep(3000); }
catch(InterruptedException ex){}
System.out.println("setting condition to satisfied");
condition.setSatisfied();
}
}
class Condition {
private volatile boolean satisfied;
public void setSatisfied() {
satisfied=true;
}
public boolean isSatisfied() {
return satisfied;
}
}
The big advantage of this encapsulation is that it is easy to extend. Suppose you want to allow a thread to wait for the condition instead of polling it. Taking the code above it’s easy:
class WaitableCondition extends Condition {
public synchronized boolean await() {
try {
while(!super.isSatisfied()) wait();
return true;
} catch(InterruptedException ex){ return false; }
}
public synchronized void setSatisfied() {
if(!isSatisfied()) {
super.setSatisfied();
notifyAll();
}
}
}
class Waiter implements Runnable {
final WaitableCondition condition;
final String name;
Waiter(WaitableCondition c, String n) { condition=c; name=n; }
public void run() {
System.out.println(name+": waiting for condition");
boolean b=condition.await();
System.out.println(name+": "+(b? "condition satisfied": "interrupted"));
}
}
Without changing the other classes you can now extend your test case:
public class Test {
public static void main(String[] args) {
WaitableCondition c=new WaitableCondition();
new Thread(new Setter(c)).start();
new Thread(new Getter(c, "getter 1")).start();
// you can simply extend it to more than one getter:
new Thread(new Getter(c, "getter 2")).start();
// and you can have waiters
new Thread(new Waiter(c, "waiter 1")).start();
new Thread(new Waiter(c, "waiter 2")).start();
}
}
class firstThread extends Helper1
{
Thread thread_1 = new Thread(new Runnable()
{
#Override
public void run() {
try {
for (int i = 1; i <= 20; i++) {
System.out.println("Hello World");
Thread.sleep(500);
if (i == 10) {
Notify();
Wait();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class secondThread extends firstThread
{
Thread thread_2 = new Thread(new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
try {
Wait();
for(int i = 1; i<=20; i++)
{
System.out.println("Welcome");
Thread.sleep(100);
}
Notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
public class InheritanceClass {
public static void main(String[] args)
{
Thread f = new Thread(new firstThread().thread_1);
Thread s = new Thread(new secondThread().thread_2);
f.start();
s.start();
}
}
Only the first Thread has an output. Please try my code. I don't know why it happens.
The second thread does not give output, I suppose it's because of Wait() in the secondThread, I don't know what to do.
The problem is with the following code:
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
Above, the wait() and notify() calls are equivalent to this.wait() and this.notify(). However, thread1 and thread2 are separate objects so they are not ever going to communicate via this method.
In order for communication to occur, you need a shared lock object. For example:
Object lock = new Object();
firstThread = new firstThread(lock);
secondThread = new secondThread(lock);
and synchronizations like:
void wait(Object lock) {
synchronized(lock) {
lock.wait();
}
}
void notify(Object lock) {
synchronized(lock) {
lock.notify();
}
}
Disclaimer: I would never do this personally, however it does answer the OP's question.
This code is really confusing, which is making it hard to see the underlying problem.
You should never start a class with a lower-case letter since it makes it look like a method/field name (e.g. firstThread).
I'm pretty sure Wait and Notify have no reason to be synchronized.
Why does secondThread inherit from firstThread??? Actually, why do you have those two classes at all? You should just make an anonymous inner class from Helper1 or something.
Anyway, the problem is that when you call Notify() in thread1 it notifies itself, not thread2.