我试图理解ReentrantLock在Java中的内部工作。
我创建了一个例子: -
bash
现在我的问题是有2个线程对象和2个可运行对象和2个线程。每个线程应在其自己的堆栈帧上运行run方法,以用于不同的可运行对象。如果每个线程在具有不同runnable对象的堆栈上运行自己的run方法,则输出应该是不同的。
我见过我们创建几个线程的示例,我们将共享对象传递给这些线程,我们在该共享对象的方法中锁定和解锁。这里没有共享对象。有两个runnable对象传递给2个线程对象,但runnable对象表现为共享对象。
请您解释一下可能导致此输出的原因?或者可以提供相同的澄清
由于
答案 0 :(得分:3)
此处对象未共享
两个线程都运行自己的Runnable实例是正确的,因此两个线程都没有共享一个公共的Runnable。
但是两个Runnable实例都使用了所包含类的共享对象,这就是锁对象。因此,他们在这个对象的帮助下彼此同步。只要另一个线程通过调用
保持锁定,就会阻塞一个线程lock.tryLock(500, TimeUnit.MILLISECONDS)
为什么两个Runnable实例都可以访问锁定对象,该对象被定义为类ReentrantLockingDemo的私有变量,这里将解释Anonyomous Classes。
所以当你写
private Runnable newRunable() {
return new Runnable() {...};
}
您创建了一个从Runnable继承的匿名内部类的新实例,该实例可以访问外部类的所有final(或Java 8也是所有有效的最终)字段。
因此,即使您没有将共享对象显式传递给Runnable实例,它们也会使用共享对象进行同步,在这种情况下是锁定对象。
答案 1 :(得分:2)
这里没有共享对象。
不会共享Runnable和Threas。
有两个共享的对象ReentrantLockingDemo.this
和ReentrantLockingDemo.this.lock
正是共享锁才能使其发挥作用。
runnable对象表现为共享对象。
您没有打印出Runnable的详细信息,因此您无法确定这一点。尝试在run()
System.out.println(this);
它应该在它之后用不同的hashCode打印类名。
总是这个锁对象在单个对象或更多对象(如上例所示)的情况下在线程之间共享以进行同步吗?
锁对象没有什么特别之处,这意味着必须共享它。共享对象的原因是由于数据结构的布局方式。您有一个ReentrantLockingDemo实例,它有一个字段,它是ReentrantLock的一个实例。没有比这更复杂或更特殊的了。
虽然在不同的对象上使用它不会起任何作用,因为实例变量也会变得线程安全,因为对象是不同的。
唯一different
个对象是两个Runnable
。在这种情况下,锁在线程之间共享
当两个线程都使用相同的对象时。在这种情况下,只有其中一个,所以毫无疑问它可以分享。
您能为上述提供任何链接吗?
有时我们会想到,因为问题很难掌握,所以必须复杂化。实际上它非常非常简单。
您只创建一个锁,因此必须共享。