Imagine the following class.
class Whatever {
Object obj;
Whatever() {
obj = new Object();
}
Object get() {
return obj;
}
}
As threads usually write to their local cache I assume the following:
If a thread A creates an instance of Whatever and a thread B calls get() on that instance, it could happen that B gets a null because the reference for obj was written in the locale cache of A only, not in the shared cache.
Am I right? And what about other kind of initializations?
I've tried to produce that behaviour with the following code.
class Main {
static Whatever whatever = new Whatever();
static class Whatever {
Object obj;
Whatever() {
obj = new Object();
}
}
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (!Thread.interrupted()) {
whatever = new Whatever();
}
});
Thread t2 = new Thread(() -> {
while (!Thread.interrupted()) {
System.out.println(whatever.obj);
}
});
t1.start();
t2.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt();
t2.interrupt();
}
}
The output is never null but I think it should be sometimes. Maybe the code is just trying it wrongly ..
Related
Can this code deadlock with thread 1 calling one and thread 2 calling two. That is, can the acquisition of the inner lock be reordered to before the acquisition of the outer one (from the POV of the other thread)?
private final Object foo = new Object();
synchronized void one() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
synchronized void two() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
No, this will not deadlock.
When synchronized methods are called the intrinsic lock of this is locked before the method’s body is executed. Here either thread 1 or thread 2 will get to run its method, and the other one will not be able to lock on the intrinsic lock of this.foo so the owner of the lock of this will be able to lock this.foo.
So for with a Simple Test :
class LockTest implements Runnable {
public final Object foo = new Object();
boolean runOne;
public LockTest(boolean runOne) {
this.runOne = runOne;
}
synchronized void one() {
System.out.println("runnin one function");
synchronized(this.foo) {
try {
System.out.println("Enter Sleep function one");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void two() {
System.out.println("running two function");
synchronized(this.foo) {
try {
System.out.println("enter sleep function two");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void run() {
if(runOne)
one();
else
two();
}
}
With this in a Main class :
while (true)
{
LockTest document2 = new LockTest(true);
LockTest document3 = new LockTest(false);
Thread tread1 = new Thread(document2);
Thread tread2 = new Thread(document3);
tread1.start();
tread2.start();
a++;
if(a==10)
break;
}
We are not locking and even watching with a Thread Dump everything is working Fine. Why? Because every time we are initializating a new Thread with a new object foo. But if that object is declared as static it will be a lock and the others threads need to wait. So from my test and POV. No, it can't be deadlocked.
public class UThread implements Runnable {
Object o;
UThread(Object o) {
this.o = o;
}
#Override
public void run() {
synchronized (o) {
System.out.println("inside before change" + Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (Exception er) {
}
o = new Object();
System.out.println("inside after change" + Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (Exception er) {
}
}
System.out.println("outside " + Thread.currentThread().getName());
}
}
public class main {
public static void main(String str[]) {
Object o = new Object();
UThread uThread = new UThread(o);
Thread th = new Thread(uThread);
UThread uThread2 = new UThread(o);
Thread th2 = new Thread(uThread2);
th.start();
try {
Thread.sleep(1000);
} catch (Exception er) {
}
th2.start();
}
}
When we execute the code it print
inside before changeThread-0
inside after changeThread-0
outside Thread-0
inside before changeThread-1
inside after changeThread-1
outside Thread-1
So why second thread not taken the lock on o when I change the object.
Assigning a reference does nothing to the underlying object. All it does is copy the reference value without touching or altering the object itself. It doesn't for example, release a lock nor should it.
e.g.
Object o2 = o;
synchronized(o) {
o = new Object();
// o2 is still locked
}
// o2 is not locked
The second thread has requested a lock for the original object referenced by the o variable (the one created in your main method and passed to the constructor of the two UThread instances).
Changing the value of o inside the synchronized block of the first thread doesn't change the fact that this thread already locked the original object referenced by o, which the second thread is also waiting to lock.
I am trying to print numbers 0,1, 2 and so on using the three different threads in below order by using threadlocal variables :
0- thread 0
1- Thread 1
2- Thread 2
3- thread 0
4- Thread 1
.
.
Below is the code where i am putting an integer in the threadlocal storage and comparing it with the atomic integer which gets incremented by every thread.
public class alternate123
{
public static void main(String as[])
{
Object ob = new Object ();AtomicInteger t = new AtomicInteger(0);
Thread t1 = new Thread ( new printpattern(t,0),"t0");
Thread t2 = new Thread ( new printpattern(t,1),"t1");
Thread t3 = new Thread ( new printpattern(t,2),"t2" );
t1.start();
t2.start();
t3.start();
}
}
class printpattern implements Runnable
{
//Integer t ;
//Object ob = new Object ();
AtomicInteger ai;
private ThreadLocal<Integer> t = new ThreadLocal<Integer>() ;
public printpattern(AtomicInteger at,Integer i)
{
//
ai=at;
t.set(i);
}
#Override
public void run()
{
// TODO Auto-generated method stub
synchronized (ai) {
while (true)
{if (ai.get()%3==
t.get()) // ----------------------- null pointer exception here
{
try {
ai.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Current thread id "+Thread.currentThread().getName()+"value of integer is "+ai.get());;
ai.incrementAndGet();
ai.notify();
}
}
}
}
i am getting null while trying to do t.get() and below is the stacktrace :
Exception in thread "t2" java.lang.NullPointerException
at printpattern.run(alternate123.java:46)
at java.lang.Thread.run(Thread.java:619)
Exception in thread "t0" java.lang.NullPointerException
at printpattern.run(alternate123.java:46)
at java.lang.Thread.run(Thread.java:619)
Exception in thread "t1" java.lang.NullPointerException
at printpattern.run(alternate123.java:46)
at java.lang.Thread.run(Thread.java:619)
i am setting threadlocal variable using set method which i doubt is erroneous . Please let me know what could be the issue .
The constructor is called in your main thread, so the value is set for that thread: you have to set the threadlocal value in the run method. Just store the integer value (i param in your constructor) as a field inside printpattern class and then call t.set(i) in the run method.
P.S.: please rename printpattern to PrintPattern - it's a class.
Calling the set method will only assign the value for the current thread. You are setting the value from your main thread. So it will only be available from your main thread.
Actually, you only need 1 instance of a ThreadLocal in this case, then you can reuse it for multiple threads. But either way, it is crucial that you set the value from within the individual threads. (i.e. in your run method)
You could see a ThreadLocal<Integer> object as a Map<Thread, Integer> in a way, where the set method is equivalent to map.put(Thread.currentThread(), value). That's not really how it works internally, but from a functional point of view, that's pretty much what it does.
Here's an example that reuses the threadlocal for multiple threads. (Changes are marked with //CHANGE x comments.)
public class Alternate123 {
public static void main(String as[]) {
// CHANGE 1: create only 1 threadlocal instance.
ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();
// CHANGE 2: pass the threadlocal to the individual threads.
Thread t1 = new Thread(new printpattern(0, threadLocal), "t0");
Thread t2 = new Thread(new printpattern(1, threadLocal), "t1");
Thread t3 = new Thread(new printpattern(2, threadLocal), "t2");
t1.start();
t2.start();
t3.start();
}
}
class printpattern implements Runnable {
// CHANGE 3: keep track of the initial value
Integer startValue;
ThreadLocal<Integer> threadLocal;
AtomicInteger ai = new AtomicInteger();
public printpattern(Integer i, ThreadLocal<Integer> threadLocal) {
// CHANGE 4: don't assign the value to the threadlocal yet.
// Because we are still in the main-thread when we reach this point.
this.startValue = i;
this.threadLocal = threadLocal;
}
#Override
public void run() {
// CHANGE 5: Assign the initial value to the threadlocal
// this time we are doing it from within the individual threads.
if (this.threadLocal.get() == null) {
this.threadLocal.set(startValue);
}
synchronized (ai) {
while (true) {
if (ai.get() % 3 == t.get()) {
try {
ai.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
// CHANGE 6: I had to change something here to make it compile. Not really relevant.
System.out.println("Current thread id " + Thread.currentThread().getName() + "value of integer is ...");
ai.incrementAndGet();
ai.notify();
}
}
}
}
What will happen if I assign a new thread object to a thread variable and run it while the thread object that was bound to the variable before is still running? Will it be garbage collected and destroyed? Or will they run in parallel?
Something like this:
class ThreadExample implements Runnable {
public void run() {
// Something that runs for a long time
}
}
public class ThreadExampleMain {
public static void main(String[] args) {
// Client Code
ThreadExample e = new ThreadExample();
Thread t = new Thread(e);
t.start();
e = new ThreadExample();
t = new Thread(e);
t.start();
}
}
Will this start two threads running parallelly or will the first thread stop and be garbage collected?
If you a talking about Java then answer is: they will run in parallel. Garbage collection has nothing to do with the thread management.
You can see it with this sample code:
public class LostThread {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
final int value = i;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println(value);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
}
Main finishes after ten threads are created, but they are still running.
SYNCHRONIZATION
I have declared a class b which has a synchronized method which is accessed in class c:
class b {
String msg;
public synchronized void foo() {
System.out.print("[" + msg);
try {
Thread.sleep(1000); // Threads go to sleeep
} catch (InterruptedException e) {
System.out.println("Caught" + e);
}
System.out.println("]");
}
}
class a implements Runnable {
b ob;
Thread t;
a(String msg, b obb) {
ob = obb;
ob.msg = msg;
t = new Thread(this); // creating a thread
t.start();
}
public void run() {
ob.foo(); // calling method of class b
}
public static void main(String... a) {
b obb = new b();
a ob = new a("Hello", obb); /* PASSING */
a ob1 = new a("Synch", obb); /* THE */
a ob2 = new a("World", obb);/* MESSAGE */
try {
ob.t.join();
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Caught" + e);
}
}
}
I am expecting the output:
[Hello]
[Synch]
[World]
But the code gives:
[World]
[World]
[World]
Help me with some suggestions. I am a naive JAVA user.
use the following code to get the expected answer.
class b {
// String msg;
public void foo(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000); // Threads go to sleeep
} catch (InterruptedException e) {
System.out.println("Caught" + e);
}
System.out.println("]");
}
}
public class Threading implements Runnable {
b ob;
String msg;
Thread t;
Threading(String message, b obb) {
ob = obb;
msg = message;
t = new Thread(this); // creating a thread
t.start();
}
public void run() {
synchronized (ob) {
ob.foo(msg); // calling method of class b
}
}
public static void main(String... a) {
b obb = new b();
Threading ob = new Threading("Hello", obb); /* PASSING */
Threading ob2 = new Threading("World", obb); /* THE */
Threading ob1 = new Threading("Synch", obb);/* MESSAGE */
try {
ob.t.join();
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Caught" + e);
}
}
}
In the code you have set ob.msg=msg; msg gets overridden by the threads. So you have the same message for all the Threads.
In the constructor of each Thread of class a you are passing the same object of class b. Now all three threads are setting the value of msg of the instance of class b. So one value overrides the other. What you have is the value set by last thread i.e. World.
IMO: Save the msg as an instance variable in each thread and pass it to the foo method as a parameter.
And please follow Java naming convention i.e. Camel Casing
First of all reformat your code. It is very hard to read.
Second when you call ob.msg = msg; it overrites msg value in ob and as it is not synchronized so you cannot actually predict what the output will be.