简体   繁体   English

synchronized块没有阻塞对象

[英]synchronized block not blocking the object

I am trying to get a lock on the object for 10 seconds. 我试图锁定对象10秒钟。 I am expecting any other thread should wait for 10 seconds to use that object as it's synchronized. 我期待任何其他线程应该等待10秒才能使用该对象,因为它已经同步。

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. 我期待这一点,因为thread2应该无法访问student1直到线程对其进行锁定。

Thread 2 is not synchronized on student1 . 线程2在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. 这是因为您没有在Thread2的run()方法中同步对student1引用的访问。

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. 当你在thread1的run方法中说synchronized(student1)时,thread1将获取该student1对象的锁,进入synchronized块并执行该块内的代码。

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. 任何其他线程在同一student1引用上获取锁定的任何后续尝试都将阻塞该线程,直到thread1通过退出synchronized块释放锁定。 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. 在您的示例中,thread2不会执行任何会尝试获取thread1正在使用的锁的操作。 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). 引用对象上的字段不会获得锁定,它需要做的是输入使用相同锁定(student1)的同步块或方法。

If you add a synchronized method to Student: 如果向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: 并且在thread1运行时让thread2调用它,将thread2的run方法中的代码更改为:

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: 然后thread2将无法获取student1上的锁,以便在thread1持有时进入getName方法,并且您应该看到阻塞发生:

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. 请注意,当您启动这两个线程时,它会看到哪个将首先启动,但不保证thread1将始终在thread2之前运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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