我试图锁定对象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
,直到线程锁定它为止。
答案 0 :(得分:4)
student1
上的线程2未同步。这就是它没有等待的原因。您需要同步两个线程。
答案 1 :(得分:1)
这是因为你没有在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块释放锁定。只有当线程请求对已锁定的对象进行锁定时,才会阻塞线程,同一类的任何其他实例或锁定对象的方法/字段的任何其他访问都不允许同步。
答案 2 :(得分:0)
在你的例子中,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之前运行。