[英]synchronized block not locking the object reference
class Demo
{
void demo()
{
System.out.println("Inside demo of "+Thread.currentThread().getName());
try
{
Thread.sleep(1000000);
}
catch(InterruptedException exc)
{
System.out.println(Thread.currentThread().getName()+" interrupted");
}
}
}
class MyThread1 implements Runnable
{
Thread thread;
Demo d;
MyThread1(String name, Demo ob)
{
d = ob;
thread = new Thread(this, name);
thread.start();
}
@Override
public void run()
{
System.out.println(thread.getName()+" starting");
synchronized(d)
{
d.demo();
}
System.out.println(thread.getName()+" ending");
}
}
class MyThread2 implements Runnable
{
Thread thread;
Demo d;
MyThread2(String name, Demo ob)
{
d = ob;
thread = new Thread(this, name);
thread.start();
}
@Override
public void run()
{
System.out.println(thread.getName()+" starting");
d.demo();
System.out.println(thread.getName()+" ending");
}
}
class TimePass
{
public static void main(String args[])
{
Demo d = new Demo();
MyThread1 mt1 = new MyThread1("Thread 1", d);
MyThread2 mt2 = new MyThread2("Thread 2", d);
}
}
输出是
线程1开始
线程1的内部演示
线程2开始
线程2的内部演示
由于Thread.sleep(1000000)
,执行尚未结束。
我已经将类Demo
的相同实例传递给类MyThread1
和MyThread2
的构造函数。
Demo d = new Demo();
MyThread1 mt1 = new MyThread1("Thread 1", d);
MyThread2 mt2 = new MyThread2("Thread 2", d);
在MyThread1
对d.demo
的调用在synchronized
块中。
MyThread2
对d.demo
的调用不在 synchronized
块中。
因此,在执行MyThread1
时,由于synchronized
块,应该锁定d
的监视器,从而导致MyThread2
拒绝访问d.demo()
。
但是,这没有发生。
预期的输出是
Thread 1 starting
Inside demo of Thread1
Thread 2 starting
(输出在Thread.sleep(1000000)
完成之前。)
所以,我的基本问题是: 如何MyThread2.d.demo()
成功执行,即使MyThread1.d.demo()
尚未完成的synchronized
块?
因此,在执行MyThread1时,由于存在
synchronized
块,因此应锁定d
的监视器,从而导致MyThread2对d.demo()
的访问被拒绝。
仅当MyThread2也具有synchronized
块时,才会发生这种情况。 当一个线程在对象上同步时,如果其他线程也尝试在同一对象上同步,则其他线程将被阻止。 如果他们不同步,它们就不会同步。 没有什么可以阻止从不同步对象的线程访问对象的。
同步是一种协作机制。 仅当所有线程一起工作时,它才起作用。
synchronization
仅发生在Thread1
。 由于Thread2
在d
上不synchronize
,因此可以在Thread1持有锁的同时调用demo()
。
你似乎误会使用的synchronized
。 同步仅在尝试输入公共对象的同步块的其他线程中发生。
同步是一种协作。 每一方都说,当另一方处于关键部分时,他们不会。
您仅在一个线程中synchronized
访问了Demo
实例的demo
方法
synchronized(d)
{
d.demo();
}
另一个是直接访问它
d.demo();
他们违反了这些协作规则,因此您无法承担任何责任。
JLS中对此进行了解释
获取与对象相关联的锁本身并不能防止其他线程访问该对象的字段或调用该对象上的未同步方法。 其他线程也可以以常规方式使用同步方法或同步语句来实现互斥。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.