避免在Java中同步(这个)?

避免在Java中同步(这个)?

每当出现关于Java同步的问题时,一些人都非常想指出synchronized(this)应该避免。相反,他们声称,私有引用上的锁是首选的。

提出的一些理由如下:

其他人,包括我,认为synchronized(this)是一个经常使用的成语(也是在Java库中),是安全的,也是很好理解的。这是不应该避免的,因为您有一个bug,并且您不知道您的多线程程序中发生了什么。换句话说,如果它是适用的,那就使用它。

我有兴趣看到一些真实世界的例子(没有foobar的东西),避免锁定。thissynchronized(this)也能做好这份工作。

因此:你应该总是避免synchronized(this)用私人引用上的锁替换它?


一些进一步的信息(随着答案的提供而更新):

  • 我们讨论的是实例同步。
  • 两个隐式(

    synchronized

    方法)的显式形式。

    synchronized(this)

    被认为
  • 如果你引用布洛赫或其他权威人士的话,不要遗漏你不喜欢的部分(例如有效的Java,线程安全项目:

    通常情况下,它是实例本身的锁,但也有例外。)

  • 如果您需要在您的锁定中使用粒度而不是

    synchronized(this)

    提供,然后

    synchronized(this)

    是不适用的,所以这不是问题所在


月关宝盒
浏览 318回答 3
3回答

三国纷争

我将分别讨论每一点。一些邪恶的代码可能盗取你的锁(这个很流行,也有一个“意外”变体)。我更担心不慎..这等于是this是类公开接口的一部分,应该有文档记录。有时需要其他代码使用您的锁的能力。对于像这样的事情,这是正确的。Collections.synchronizedMap(参见javadoc)。同一类中的所有同步方法都使用完全相同的锁,从而降低了吞吐量。这是过于简单化的想法;只是摆脱了synchronized(this)解决不了问题。正确的吞吐量同步将需要更多的思考。你(不必要地)暴露了太多的信息这是#1的一个变体。synchronized(this)是你界面的一部分。如果你不想/不想暴露这件事,就不要这样做。

繁花如伊

当您使用同步(此)时,您将类实例用作锁本身。这意味着当锁由线程1获得时,线程2应该等待。假设以下代码public void method1() {     do something ...     synchronized(this) {         a ++;           }     ................}public void method2() {     do something ...     synchronized(this) {         b ++;           }     ................}方法1修改变量a和方法2修改变量b,应该避免由两个线程并发修改同一个变量。但当螺纹1改性a和螺纹2改性b它可以在没有任何比赛条件的情况下执行。不幸的是,上面的代码将不允许这样做,因为我们对锁使用相同的引用;这意味着,即使线程不处于竞争状态,也应该等待,而且显然代码牺牲了程序的并发性。解决办法是使用2不同锁二不同的变量。  class Test {         private Object lockA = new Object();         private Object lockB = new Object();public void method1() {     do something ...     synchronized(lockA) {         a ++;           }     ................}public void method2() {     do something ...     synchronized(lockB) {         b ++;           }     ................  }上面的示例使用更细粒度的锁(2个锁而不是一个(洛卡和锁B变量a和b),从而允许更好的并发性,另一方面,它变得比第一个示例更加复杂.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java