同步线程和锁定

齐齐:

有人可以在对象锁定的上下文中解释这两个示例之间的区别:

public void method1(){
    synchronized(this){
        ....
    }
}

StringBuffer aStringBufferObject = new StringBuffer("A");

public void method2(){
    synchronized(aStringBufferObject){
        ....
    }
}

我知道第一个示例将获得this实例的锁,第二个示例将获得aStringBufferObject实例的锁。但是我真的不了解两者的作用或区别是什么。

例如,在第二个示例中,由于锁与“ this”实例无关,线程仍将能够执行同步块内的代码吗?

我知道同步一个方法或代码块会阻止多个线程同时访问该块/方法,但是指定要锁定的对象的目的是什么,以及在对象中的指定方式有何不同上面的例子?

Vineet Reynolds:

指定要锁定的对象的目的是什么?

通常,thisClass实例实例进行同步更容易(对于静态方法)。但是,在某些情况下,您将需要在特定对象上进行同步,而不是隐式锁定(this)。此类情况包括:

  • 您想要不使用来同步对基元的访问this您只能在上进行同步,Object因为每个Object都与Java中的隐式监视器关联。基元没有此类隐式监视器,因此您需要使用锁对象。使用包装器类是一个糟糕而错误的选择,尤其是当您最终修改了受保护块中的锁定对象时
  • 您要在实际上保护关键部分的对象上进行同步,而在同步时this并不能保证线程安全。例如,如果您要同步对ArrayList在class 实例之间共享的实例的访问A,则对的实例进行同步A是没有用的。一个线程可能会创建的新实例A并获得对该列表的访问权限,而另一个线程正在对其进行修改。如果使用所有线程都必须争用的其他锁,则可以保护列表;否则,您可以保护列表。此锁可以是与关联的锁A.class,但也可以是将提供相同保证的任何对象。
  • 您要执行锁拆分,以确保不同的受保护块受不同的锁(而不是同一锁)保护。换句话说,如果允许不同的线程获取不同的锁来访问不同的关键部分是线程安全的,则每个关键部分都可以拥有不同的锁。

以下是分割锁用法的示例:

private Object method1Lock = new Object();
private Object method2Lock = new Object();

public void method1(){
    synchronized(method1Lock){
        ....
    }
}

public void method2(){
    synchronized(method2Lock){
        ....
    }
}

当可以确保并发执行method1并且method2不违反类不变式时,可以使用分割锁这样,您可以提高需要访问同一对象但将调用不同方法的线程的性能。


关于另一个问题,

例如,在第二个示例中,由于锁与“ this”实例无关,线程仍将能够执行同步块内的代码吗?

在第二个示例中,任何进入受保护区域的线程都必须获取与关联的锁aStringBufferObject如果其他线程持有该锁,则当前线程将不会继续进行。指定时this,线程必须获取与当前对象关联的锁。在这两种情况下,线程都必须获得一个锁。这些示例仅在用作锁的对象方面有所不同。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章