Thread loses lock and gives another thread a chance to execute - java

Here I have an object with 2 threads and providing lock on object by print() but after some loop it losing lock and execute the second thread and it will change the value of breakLoop and first thread will be terminate.
public class ThreadLock {
public static void main(String[] args) {
Entity entity=new Entity();
RunnableClass runnable = new RunnableClass(entity);
Thread threadClass= new Thread(runnable);
Thread threadClass2= new Thread(runnable);
threadClass.setName("First Thread");
threadClass2.setName("Second Thread");
threadClass.start();
threadClass2.start();
}
}
class RunnableClass implements Runnable{
Entity entity;
public RunnableClass(Entity entity) {
this.entity=entity;
}
public void run(){
if(Thread.currentThread().getName().equalsIgnoreCase("First Thread"))
entity.print();
else{
entity.print("");
}
}
}
class Entity{
public void print(String str){
System.out.println("Non sysncronized method accessed by "+Thread.currentThread().getName());
breakLoop=false;
}
boolean breakLoop=true;
//lock will work for same object
public synchronized void print(){
System.out.println("Lock aquired by : "+Thread.currentThread().getName());
while (breakLoop) {
System.out.println("hhhhhhhhhhhhhh");
}
System.out.println("Lock released by : "+Thread.currentThread().getName());
}
}

The first thread having the lock doesn't stop the second thread from calling the Entity.print(String) method, because that method doesn't try to acquire the lock. Calling print(String) sets the breakLoop flag to false.
(When the flag value becomes visible to the other thread is not well-defined due to memory visibility issues --it would be better to make the breakLoop instance variable volatile-- but that doesn't necessarily mean the second thread will never see the change to the instance variable. Memory visibility issues are more apparent on some platforms than others.)
If you change the print(String) method to be synchronized, it will hang waiting for the first thread to finish.

Related

When we call thread.start() which thread is invoked first

Here my code is:
public class Child extends Thread {
public void run(){
synchronized (this)
{
for(int i=1;i<=5;i++)
{
System.out.println("child thread");
}
}
}
}
class ThreadTest{
public static void main(String []a) {
Child child=new Child();
**child.start();**
synchronized (child)
{
for(int i=1;i<=5;i++)
{
System.out.println("parent thread");
}
}
}
}
It first prints "parent thread" after that it prints "child thread" but my doubt is, when we invoke start() method there is a chance to invoke child thread before main thread. But it always prints "parent thread" after that "child thread". can any one explain?
Somewhere inside the child.start() call (i.e., before start() returns) the new thread is created, and it becomes eligible to run. From that point on, it's a race to see which thread will reach it's respective synchronized(...) block first. There's no way to know which one will win, and there's no reason to think that it will be the same winner every time.
P.S.: Synchronizing on a Thread object is not a good idea. The Thread class also synchronizes on Thread instances for its own purposes, and there is a risk that your use of the Thread object as a lock could interfere with the Thread class's use of it.
A good habit is to synchronize on a private object.
class MyClass {
private final Object myLock = new Object();
SomeType someMethod(...) {
synchronized(myLock) {
....
}
}
}

synchronized keyword and locks on instance methods

I'm studying concurrency at the moment and I was learning about blocking threads.
I know that a thread can come to a blocked state when the corresponding attached task tries to access a method that is locked because another thread acquired the lock.
So from what I've read the task blocks and wait until it can access that method and so goes on with its business (namely, the rest of the run() method).
So why does this code exits like the task could call syn.getI() and access the variable in an "erroneous" state (even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI() ) ? where am I wrong on this?
public class SynchronizedClass {
private int i;
private boolean flag=true;
public SynchronizedClass(int i){
this.i=i;
}
public int getI(){
return i;
}
public boolean getFlag(){
return flag;
}
public synchronized void manipulate(){
i=(i*2)+1; //odd number
Thread.yield();
i= i+1; //even number
}
public void close(){
flag=false;
}
}
public class MyThread implements Runnable {
//auto-managed runnable
Thread t;
SynchronizedClass syn;
public MyThread(SynchronizedClass syn){
this.syn=syn;
t=new Thread(this);
t.start();
}
#Override
public void run() {
while(syn.getFlag()==true){
syn.manipulate();
if (syn.getI()%2!=0){
syn.close();
System.out.println("exit");
}
}
}
public static void main(String[] args) {
SynchronizedClass syn = new SynchronizedClass(1);
for(int i=0;i<4;++i)
new MyThread(syn);
}
}
even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI()
That's the mistake you're making, I believe.
Just because one method is synchronized doesn't implicitly mean that anything else is synchronized. It's not like one thread owning the monitor associated with an object stops other threads from accessing that object - it just stops other threads from acquiring the monitor.
If you make the getI() method synchronized, then one thread owning the monitor due to manipulate() means that other threads calling getI() on the same object would have to wait, in order to acquire the monitor.

understanding nested locks in java

i want to understand this:
String string;
public Test(String string){
this.string = string;
.....
}
public void foo(newObjectPerCall o) {
synchronized (o) {
//each thread can enter here because the object passed is always different
....
synchronized (string) {
// acquire this lock if the String is free.
}
}
}
public synchronized void function() {
}
public static void main(){
Test test = new Test("hello");
for(int i = 0; i < 10;i++){
WorkerThread workerThread = new WorkerThread(test);
workerThread.start();
}
}
thread class
public class WorkerThread extends Thread {
private Test test;
public WorkerThread(Test test) {
this.test = test;
}
#Override
public void run() {
while (true) {
test.foo(new Object());
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.function();
}
}
}
my doubts are:
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes. They will block, waiting to acquire the monitor for string.
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
Yes, it's entirely independent of the other monitors. A synchronized instance method is just equivalent to one whose body is
synchronized (this) {
...
}
If no other thread already owns the monitor for this, the "new" thread can acquire it regardless of what other monitors are owned. But as all your worker threads are using the same instance of Test, only one of them will be able to be "in" function() at a time. That can be at the same time as another thread is executing foo() though.
Sorry I know only the answer only for the first question
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes

How Java manage following scenario?

I tried some code to justify the reliability of synchronized block locking mechanism. Consider my sample code
My clocking object.
public class MyLock {
final static Object lock=new Object();
}
Class with synchronized blocks
public class Sample {
public void a(String input) {
System.out.println(input+" method a");
synchronized (lock) {
System.out.println("inside synchronized block in a");
try {
System.out.println("waiting in a");
Thread.sleep(5000);
System.out.println("calling b() from a");
new Sample().b("call from a");
System.out.println("waiting again in a");
Thread.sleep(5000);
System.out.println("Running again a");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void b(String input) {
System.out.println(input+" method b");
synchronized (lock) {
System.out.println("bbb " + input);
}
}
}
Test1 class
public class Test1 implements Runnable{
public static void main(String[] args) {
new Thread(new Test1()).start();
new Thread(new Test2()).start();
}
#Override
public void run() {
new Sample().a("call from main");
}
}
Test2 class
public class Test2 implements Runnable {
#Override
public void run() {
new Sample().b("call from main");
}
}
I just did this because I thought there will be a dead lock scenario if same thread witch holding the lock is going to access another method witch locked using same lock. Now consider the out put
call from main method a
call from main method b
inside synchronized block in a
waiting in a
calling b() from a // i thought this will cause a dead lock
call from a method b
bbb call from a
waiting again in a
Running again a
bbb call from main
Now you can see there is no such issue. My question is how Java manage this situation?
synchronized block is Reentrant
By default the lock (mutex to be precise) used in synchronized block is Reentrant, which means if the same thread tries to acquire the same lock again it will not have to wait and will immediately enter the critical block as it already owns that lock.
Where is Reentrancy useful?
Simple answer is Recursion.
Consider the scenario of recursion on a synchronized method,
int synchronized method(int param){
//... some logic
method(param - 1);
}
In this example you would not want the same thread to be blocked for the same lock, as it will never be able to proceed.
Deadlock occurs in this scenario:
Thread A acquires lock A
Thread B acquires lock B
Thread A tries to acquire lock B
Thread B tries to acquire lock A
Now in this situation no one will be able to proceed and hence deadlock. But in your scenario there is only one lock, so the other thread will just wait for the first thread to leave the lock and then continue.
Since your lock object is static it is shared among threads. Once thread A has acquired the lock, and when thread B enters method B of sample class it tries to acquire the same lock Which is owned by thread A. So there is no chance of deadlock.
Problem could have been where thread A tries to acuire the lock it already holds in method B, but this hasnt happened in your case as synchnorized block itself is reenterant but if you would have implemented your own lock class and if you wouldnt have cjecked for renterency, there would have been a dead lock.

How locks obtained in multithreading and on which object?

Class ThreadTest extends Thread {
public synchronized void run() {
}
public static void main(String args[])
{
Thread t1=new ThreadTest();
Thread t2=new ThreadTest();
t1.start();
t2.start();
}
}
I want to know in above scenario, how locks obtained and on which object?
Does above scenario valid?
As locks are obtained on a calling object in method synchronisation then in above scenario on which object lock will be obtained. One more question who(or which object) invokes the run method?
Thanks,
-Abhishek
t1 has the lock of the t1 instance.
t2 has the lock of the t2 instance.
But your example doesnt make much sense..
Maybe this example will help you:
public class Test extends Thread {
private String name;
public Test(String name) {
this.name = name;
}
public synchronized void run() {
System.out.println(name);
while(true)
{
// loop endless
}
}
public static void main(String args[])
{
Thread t1= new Test("t1");
Thread t2= new Test("t2");
t1.start();
t2.start();
}
}
The output is:
t1
t2
You have started both the threads, but it depends on JVM which thread it might execute, so depending upon the thread which starts executing will acquire the lock first and the second thread cant be on running state till the first thread stops.
but in your case as both are different thread instances they run parallel, as the lock is acquired at the object level.
Your example doesn't make that much sense, because locks are on a per-instance level, not on a per-class level as you might wanted to use them.
I think you got it wrong a bit. The thread is wrapping up the code that is executing commands. These executions often contain access on other objects. That is the point, where locking comes into the game. Each of these objects have a monitor that can be obtained by threads. However, only one thread can obtain the lock at a time. Thus, other threads are enqueued and can access object as soon as the current holder releases it, trivially by exiting a synchronized code block.
I think you might wanted to do something like this:
class ThreadTest extends Thread
{
private final Foo f;
public ThreadTest(Foo f,int i)
{
super(""+i);
this.f = f;
}
#Override
public void run()
{
f.bar();
}
public static void main(String args[])
{
Foo f = new Foo();
Thread t1 = new ThreadTest(f,1);
Thread t2 = new ThreadTest(f,2);
t1.start();
t2.start();
}
public static class Foo
{
public synchronized void bar()
{
System.out.print("hello form Thread ");
System.out.println(Thread.currentThread().getName());
}
}
}
Formal Definition
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
If what you want is to have only one thread execute at a time (What's the point) then you should call a static method and call that from inside your run(), there is only one static method for all object of a class
How do synchronized static methods work in Java?

Categories