简体   繁体   中英

synchronized block not blocking the object

I am trying to get a lock on the object for 10 seconds. I am expecting any other thread should wait for 10 seconds to use that object as it's synchronized.

Here is the code:

public class Test {

    Student student1=new Student(1,"sachin");

    Thread thread1 = new Thread("My Thread 1"){
        public void run(){
                synchronized(student1){
                    try {
                        System.out.println("in thread1,acquired student1 and will wait for 10 sec");
                        sleep(10000);
                        System.out.println("Leaving the lock on student1");
                    } catch (InterruptedException e) {
                    }
                }
            }
    };

    Thread thread2 = new Thread("My Thread 2"){
        public void run(){
            System.out.println(String.valueOf(student1.name) +"   "+ student1.roll);
        }
    };

    public class Student {
        int roll;
        String name;
        public Student(int roll,String name)
        {
            this.name=name; this.roll=roll;
        }
    }

    public static void main(String a[]){
        Test test = new Test();
        test.thread1.start();
        test.thread2.start();
    }
}

Output:

in thread1, acquired student1 and will wait for 10 sec
sachin   1
Leaving the lock on student1

Expected output:

in thread1, acquired student1 and will wait for 10 sec
Leaving the lock on student1
sachin   1

I am expecting this because, thread2 shouldn't be able to access the student1 until thread leaves the lock on it.

Thread 2 is not synchronized on student1 . That's why it is not waiting. You need to synchronize both threads.

This is because you're not synchronizing your access to student1 reference in Thread2's run() method.

System.out.println(String.valueOf(student1.name) +"   "+ student1.roll);

should be

synchronized(student1){
  System.out.println(String.valueOf(student1.name) +"   "+ student1.roll);
}

when you say synchronized(student1) in thread1's run method, thread1 will acquire a lock on that student1 object, enters the synchronized block and executes code within that block.

Any subsequent attempts by any other thread to acquire a lock on the same student1 reference will block that thread, until thread1 releases the lock by exiting the synchronized block. Threads will be blocked only when they're requesting for a lock on an already locked object, any other instances of the same class or any other access of locked object's methods/fields without synchronization is always allowed.

In your example thread2 doesn't do anything that will attempt to acquire the lock that thread1 is using. Referencing fields on the object doesn't acquire a lock, what it needs to do is to enter a synchronized block or method that uses the same lock (student1).

If you add a synchronized method to Student:

public synchronized String getName() {
    return name;
}

and have thread2 call it while thread1 is running, changing the code in thread2's run method to:

System.out.println(String.valueOf(student1.getName()) +"   "+ student1.roll);

then thread2 won't be able to acquire the lock on student1 in order to get into the getName method while thread1 is holding onto it, and you should see blocking take place:

c:\Users\ndh>java Test
in thread1,acquired student1 and will wait for 10 sec
Leaving the lock on student1
sachin   1

Be aware when you start the two threads it's a race to see which will start first, it's not guaranteed that thread1 will always run before thread2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM