About Question enthuware.ocpjp.v7.2.1343 :

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
bluster
Posts: 60
Joined: Wed Apr 23, 2014 6:38 pm
Contact:

About Question enthuware.ocpjp.v7.2.1343 :

Post by bluster »

Piece of trivia.. It will not deadlock easily.

I added

Code: Select all

static AtomicInteger counter = new AtomicInteger();
to the class, then

Code: Select all

System.out.println("Counter from one: " + counter.getAndIncrement());
and

Code: Select all

System.out.println("Counter from two: " + counter.getAndIncrement());
after the respective lines printing the StringBuffers.

Finally I wrapped the entire main inside a while (true) infinite loop. The purpose was to see how many interactions it would take until the deadlock. Unfortunately every run blew up from lack of memory for new threads, and only for that reason.

Below is pasted the end of one run, where over 36,000 interactions went by until the JVM croaked out of memory, without the satisfaction of a deadlock. If someone can see a mistake in the code, please let me know, I wanted to see the deadlocking fireworks. Thanks!
Counter from one: 36860
Counter from two : 36861
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

Try this code:

Code: Select all

public class DeadlockTest {

    static StringBuffer sb1 = new StringBuffer();
    static StringBuffer sb2 = new StringBuffer();

    public static void main(String[] args) throws Exception {
        int i = 0;
        while (true) {
            System.out.println("Starting iteration " + i++);
            Thread t1 = new Thread(
                    new Runnable() {
                public void run() {
                    synchronized (sb1) {
                        sb1.append("X");
                        try {
                            Thread.sleep((int) Math.random() * 1000);
                        } catch (Exception e) {
                        }
                        synchronized (sb2) {
                            sb2.append("Y");
                        }
                    }
                    System.out.println(sb1);
                }
            });
            t1.start();
            Thread t2 = new Thread(
                    new Runnable() {
                public void run() {
                    synchronized (sb2) {
                        sb2.append("Y");
                        try {
                            Thread.sleep((int) Math.random() * 1000);
                        } catch (Exception e) {
                        }
                        synchronized (sb1) {
                            sb1.append("X");
                        }
                    }
                    System.out.println(sb2);
                }
            });
            t2.start();
            t1.join();
            t2.join();
        }

    }
}
HTH,
Paul.
If you like our products and services, please help us by posting your review here.

ewebxml
Posts: 78
Joined: Sun Jun 30, 2013 10:04 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by ewebxml »

For both thread instances you have a synchronized block
nested within a synchronized block .

Question 1: In practice, is this unconventional
OR
would this be looked upon negatively in practice?


Question 2: Can one generalize if nested synchronized blocks will always
lead to a deadlock?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

1. No, it is not unconventional. If you need to lock multiple resources, this is the way to do it. What is looked at negatively is if you acquire multiple resources in a different order(i.e. lock a and b in one place, and lock b and a in another). The correct way is to lock them in the same order (if you have to lock them from different classes).

2. If you lock them in a different order, you will run into a deadlock. If you lock them in the same order, there will never be a deadlock.
If you like our products and services, please help us by posting your review here.

abutalib
Posts: 12
Joined: Wed Aug 08, 2018 2:56 am
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by abutalib »

I don't understand.

By locking a static field sb1, doesn't that automatically lock (TestClass.class)? Therefore, the second thread will never be able to acquire the lock on sb2 because (TestClass.class) is already locked?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

>By locking a static field sb1, doesn't that automatically lock (TestClass.class)?

No, where did you read that?
If you like our products and services, please help us by posting your review here.

abutalib
Posts: 12
Joined: Wed Aug 08, 2018 2:56 am
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by abutalib »

Because if you synchronize a static method, it synchronizes the TestClass.class.

So then my question, if I lock a field (static or instance) it locks that field only and nothing else? The instance holding will not be locked as well?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

abutalib wrote:
Thu Feb 07, 2019 3:20 am
Because if you synchronize a static method, it synchronizes the TestClass.class.
Yes, just like an instance method uses the lock on the "this" object, the static method uses the lock of the Class object of that class.

But when you synchronize directly on an object (i.e. synchronized( anyObjectReference) ) then the lock associated with that object is used. Whether that reference is a static member or an instance member of a class is immaterial to the object pointed to by that reference.
So then my question, if I lock a field (static or instance) it locks that field only and nothing else? The instance holding will not be locked as well?
No. You need to understand that a lock is always associated with an object, but it is not the object that are locked. It is a piece of code that is locked from being executed by other threads. Instead of thinking that you are locking an object, think of it like you are using the lock associated with an object to lock a block of statements.

Go through a good book on this topic to make sure you understand this correctly because it is not possible to explain this topic fully in a forum post.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

abutalib
Posts: 12
Joined: Wed Aug 08, 2018 2:56 am
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by abutalib »

The second quote was a bad phrasing on my side. I think I got it.

When we synchronize on an object, the thread that acquires the lock first will execute the block of code uninterrupted by other threads as long until it has released the lock.

As for these multiple locks, they are usually done with the help of private fields.

Am I correct?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

abutalib wrote:
Thu Feb 07, 2019 4:02 am
As for these multiple locks, they are usually done with the help of private fields.

Am I correct?
Can't really say. Difficult to generalize like that.
If you like our products and services, please help us by posting your review here.

Javier
Posts: 66
Joined: Mon Feb 20, 2017 12:31 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by Javier »

Hi Paul!
is it correct to say that the TestClass holds an anonymous Thread class and the Thread class implements in its consctructor the Runnable interface?
So this code is like if we write:
TestClass extends Thread, and Thread implements Runnable?
Thank you in advance.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

Yes, you can think of it that way. You would create two instance of TestClass instead of the anonymous classes.
But I am not sure what you mean by this sentence, " Thread class implements in its consctructor the Runnable interface". Thread class does implement Runnable but what do you mean by "in its constructor"?

Please post code to show what you mean to avoid any confusion.
If you like our products and services, please help us by posting your review here.

Javier
Posts: 66
Joined: Mon Feb 20, 2017 12:31 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by Javier »

Code: Select all

 public static void main(String[] args){
new Thread 
[u]([i]//here is the beginning of the constructor of Thread Class [/i] 
[/u]         new Runnable()          
{             public void run()             
{                 synchronized(sb1)                 
{                     sb1.append("X");                     
                      synchronized(sb2)                    
 {                       sb2.append("Y");
                     }                 
}                 System.out.println(sb1);            
 }          
}       
[u][i]//here is the end of the constructor of the Thread Class
[/u][/i]).start();
That is why I said "the Runnable interface is implemented in the constructor of the Thread Class".

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.ocpjp.v7.2.1343 :

Post by admin »

OK, I see now what you mean.
If you like our products and services, please help us by posting your review here.

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 33 guests