请考虑以下事项:
class A {
public static void main(String[] args) throws InterruptedException
{
final A a = new A();
new Thread()
{
public void run()
{
a.intrudeLock();
};
}.start();
Thread.sleep(1000);
new Thread()
{
public void run()
{
a.doSomethingAfterLocking();
};
}.start();
}
synchronized void doSomethingAfterLocking() throws InterruptedException
{
System.out.println("aquired lock");
Thread.sleep(10000);
System.out.println("finished stuff");
}
void intrudeLock()
{
System.out.println("don't need object's lock");
}
}
通过锁定机制 - 预期输出(至少在大多数情况下):
获得锁定 不需要对象的锁定 完成的东西
我不是在问这个输出为什么,并且理解第二个线程不需要锁定其方法调用并因此可以入侵的原因。
现在这是我的疑问 - 当一个线程获得锁定时,它的意图是获得对象的排他性,并且直观地执行环境应该阻止其他线程的任何状态改变。但这不是Java实现它的方式。是否有理由设计这种机制?
答案 0 :(得分:1)
当一个线程获得锁定时,它的目的是获得对象的排他性,并且直观地执行环境应该 防止其他线程进行任何状态更改。。
小修正:
当线程获得锁定时,其意图是获得排他性 对象的监视器和直观的执行环境 应该防止等待的其他线程的任何状态更改 (需要)获得相同的锁。*
它完全由程序员指定是否希望只有在获取锁之后才能使用某些字段/资源。如果您有一个只能由一个线程访问的字段,那么它不需要同步(获取锁定)。
必须注意的重点是,完全由程序员根据程序中的代码路径同步对字段的访问。例如,字段可以由一个代码路径中的多个线程访问(调用同步),并且可以仅由另一个路径中的一个线程访问。但由于很有可能两个代码路径可以被不同的线程同时访问,因此在进入上述任何代码路径之前应该获得锁定。
现在,JIT可能决定忽略你的锁定请求( lock-elision ),如果它认为它们是不必要的(比如试图锁定永远不会逃脱的方法本地字段)。