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.
Related
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 ..
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.
thread t1 is calling test1() method of Test class object ob.
thread t2 is calling test1() method of Test class object ob in synchronized block.
t1 is able to call test1() method of ob even though test1() method call of ob is in synchronised block of thread t2.
The code is given below:
class Test {
void test1() {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test1!");
}
}
void test2() {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test2!");
}
}
}
class NewThread1 implements Runnable {
Thread t;
String name;
Test target;
NewThread1(Test ob, String threadname) {
target = ob;
name = threadname;
t = new Thread(this, name);
}
public void run() {
target.test1();
}
}
class NewThread2 implements Runnable {
Thread t;
String name;
Test target;
NewThread2(Test ob, String threadname) {
target = ob;
name = threadname;
t = new Thread(this, name);
}
public void run() {
synchronized(target) {
target.test1();
}
}
}
class Test1 {
public static void main(String args[]) {
Test ob = new Test();
NewThread1 t1 = new NewThread1(ob, "t1");
NewThread2 t2 = new NewThread2(ob, "t2");
t2.t.start();
t1.t.start();
try {
t1.t.join();
t2.t.join();
} catch(InterruptedException e) {
System.out.println("Main thread interrupted");
}
System.out.println("Main thread exiting");
}
}
Since NewThread1#run() is not synchronized it will not try to get the monitor on the target and it will therefore not be blocked, it can call the method on the target even if another thread holds the monitor of it.
Synchronized can only exclusively lock out other threads if all threads compete against the same monitor with a synchronized section. (It does not matter of you call test1 or test2 the check happens in the synchronize based on the target). What you could do is to make test1 and test2 synchronized methods, then they will try to reserve the monitor of the instance in all cases). Same is not only true for exclusive execution, but also for any memory access guarantees (happens-after) you might want to get out of a synchronized block.
BTW you don’t need different thread classes, if you only use one (the one with the synchronized) it works like expected.
Thread t1 = new NewThread2(ob, "t1");
Thread t2 = new NewThread2(ob, "t2");
However if your scope of locking is narrow, it is much better to localize the locking inside (all) instance methods of the target Test, because then you can never call them with a missing synchronized (and you can switch to other locking primitives without the caller having to know).
void synchronized test1() {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test1!");
}
}
Or
void test1() {
synchronized(this) {
while(1 == 1) {
System.out.println(Thread.currentThread().getName() + " test1!");
}
}
}
I have two different objects but
they are equals (obj1 != obj2, but obj1.equlas(obj2))
How can I use synchronization/lock for this objects like one?
For example:
...
synchronized(obj) {
doSomething(obj);
}
...
I want to lock it if one of the equals() object already doing something in the same time.
There is no way to use just one synchronized (object) and get both objects synchronized.
The solutions is:
synchronized (obj) {
synchronized (obj2) { ......
but if you invert the order in onother thread you can get a dead lock.
or the other solution, one I suggest, is to make your obj static and use to synchronize.
what you have is meaningfully equals objects, but the reference of variable that you have for obj and obj2 are pointing for different objects.
I can't say I fully understand why this could be required, but using wrapper approach may potentially help:
public class SyncOnEquals {
public synchronized Object getSync(Object o1, Object o2)
{
if(o1.equals(o2))
return this;
else
return o1;
}
}
Test:
#org.junit.Test
public void testSyncOnEqual() {
System.out.println("syncOnEqual");
Integer o1 = new Integer(125);
Integer o2 = new Integer(125);
System.out.println("o1 == o2: "+(o1==o2));
System.out.println("o1.equals(o2): "+o1.equals(o2));
SyncOnEquals sync = new SyncOnEquals();
Thread t1 = new Thread(){
public void run()
{
System.out.println("Waiting thread "+Thread.currentThread());
synchronized(sync.getSync(o1, o2))
{
System.out.println("Working thread "+Thread.currentThread());
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Finished thread "+Thread.currentThread());
}
};
Thread t2 = new Thread(){
public void run()
{
System.out.println("Waiting thread "+Thread.currentThread());
synchronized(sync.getSync(o2, o1))
{
System.out.println("Working thread "+Thread.currentThread());
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Finished thread "+Thread.currentThread());
}
};
t1.start();
t2.start();
try{
Thread.currentThread().sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
Output:
syncOnEqual
o1 == o2: false
o1.equals(o2): true
Waiting thread Thread[Thread-0,5,main]
Waiting thread Thread[Thread-1,5,main]
Working thread Thread[Thread-0,5,main]
Finished thread Thread[Thread-0,5,main]
Working thread Thread[Thread-1,5,main]
Finished thread Thread[Thread-1,5,main]
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();
}
}
}
}