繁体   English   中英

synchronized块没有阻塞对象

[英]synchronized block not blocking the object

我试图锁定对象10秒钟。 我期待任何其他线程应该等待10秒才能使用该对象,因为它已经同步。

这是代码:

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();
    }
}

输出:

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

预期产量:

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

我期待这一点,因为thread2应该无法访问student1直到线程对其进行锁定。

线程2在student1上未同步。 这就是它不等待的原因。 您需要同步两个线程。

这是因为您没有在Thread2的run()方法中同步对student1引用的访问。

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

应该

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

当你在thread1的run方法中说synchronized(student1)时,thread1将获取该student1对象的锁,进入synchronized块并执行该块内的代码。

任何其他线程在同一student1引用上获取锁定的任何后续尝试都将阻塞该线程,直到thread1通过退出synchronized块释放锁定。 只有当线程请求对已锁定的对象进行锁定时,才会阻塞线程,同一类的任何其他实例或任何其他锁定对象的方法/字段的访问都不允许同步。

在您的示例中,thread2不会执行任何会尝试获取thread1正在使用的锁的操作。 引用对象上的字段不会获得锁定,它需要做的是输入使用相同锁定(student1)的同步块或方法。

如果向Student添加同步方法:

public synchronized String getName() {
    return name;
}

并且在thread1运行时让thread2调用它,将thread2的run方法中的代码更改为:

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

然后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

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

暂无
暂无

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

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