Java 同步块不阻止对象

Java 同步块不阻止对象,java,multithreading,synchronized,Java,Multithreading,Synchronized,我正试图锁定这个物体10秒钟。我希望任何其他线程在同步时都应该等待10秒才能使用该对象 代码如下: public class Test { Student student1=new Student(1,"sachin"); Thread thread1 = new Thread("My Thread 1"){ public void run(){ synchronized(student1){

我正试图锁定这个物体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
预期输出:

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不会尝试获取thread1正在使用的锁。引用对象上的字段不会获得锁,它需要做的是输入使用相同锁的同步块或方法(student1)

如果向学生添加同步方法:

public synchronized String getName() {
    return name;
}
并让thread2在thread1运行时调用它,将thread2的run方法中的代码更改为:

System.out.println(String.valueOf(student1.getName()) +"   "+ student1.roll);
然后,当thread1抓住student1时,thread2将无法获得student1上的锁以进入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之前运行。

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

应该是

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

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


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

对thread2中对象的访问也应在同步块中。当您说
synchronized(lock)时
在thread1中,任何试图在同一实例上获得锁的其他线程都将被阻止,但您可以像访问任何其他对象一样访问
lock
字段