【问题标题】:Is it safe to call a static synchronized method from unrelated classes?从不相关的类调用静态同步方法是否安全?
【发布时间】:2016-08-13 15:10:41
【问题描述】:

我有一个类使用 static synchronized 方法进行 HTTP 调用。

我还有一个ExecutorService

有多个 Runnable 类调用此方法。该方法将接受 URL、POST/GET 信息和参数,如果响应不是 200,则返回错误代码,或者返回 XML 字符串以供 Runnable 类进一步处理。

如果多个线程在放入ExecutorService后调用该方法,这样可以吗?会失败吗?

通过ExecutorService处理多个HTTP调用的理想方式是什么?

【问题讨论】:

  • 是的,它是安全的,因为监视器对象将由类级别对象持有。
  • 如果你的静态方法是无状态的,它可能不需要同步
  • 方法为什么要同步?它是否使用任何类级别的状态?

标签: java multithreading static static-methods executorservice


【解决方案1】:

任何关于“线程安全”的问题都必须是关于可变、共享数据的问题。除非您的线程共享可变数据,否则不存在线程安全问题。

如果任何一个线程的操作都不可能将对象/组置于其他人可以看到的“坏”状态,则程序中的一个可变对象或一组可变对象是“线程安全的”线程。

保证对象/组的线程安全的最简单、最常用的方法是使用互斥(即synchronized 块和/或方法)。如果每个修改或读取数据的方法只在同一对象上的所有synchronized的代码块内这样做,并且如果mutator函数始终确保对象/组处于有效状态离开任何synchronized 块之前的状态,那么该对象/组将是“线程安全的”。


您的问题未提及任何数据。您的问题没有提到数据可能存在的任何可能的“无效”状态。您的问题谈到了一种方法,但没有提到是否有任何 other 方法可以访问相同的数据。

如果有问题的方法是staticsynchronized,那么这将保证没有两个线程能够同时进入该方法,但这不会使数据“线程安全”如果有任何其他方法可以访问或修改相同的数据。

所有访问数据的代码块和/或方法都必须是synchronized,并且它们都必须在同一个锁对象上同步。


实际上,同步每次访问 可能有点过头了。但是,如果不知道线程正在共享哪些数据,以及它们对数据做了什么,就无法知道这一点。

一切都与数据有关。

【讨论】:

  • 我将编辑我的问题,以便更清楚。谢谢你的回答,很有帮助。
【解决方案2】:

是的,这是 Java 中带有 synchronize 标签的要点:)

这就像在函数的开头锁定一个互斥锁,然后在返回时解锁同一个互斥锁。

在这种情况下,互斥锁是面向对象的,因此调用同步方法将锁定其他方法。注意

【讨论】:

  • 同步块被监视器锁定,监视块的监视器必须相同,2次调用才能互斥。并非每个同步方法都对每个线程都是专有的。如果监视器是不同的同步方法,可以并行调用。
  • 在这种情况下,监视器是类,因为它是同步方法,而不是同步块。所以如果他调用该方法,对象的监视器就会被锁定。
  • 我想我有点困惑,因为我见过一个类有同步方法的例子,但为了线程安全的目的,在调用这些方法时仍然必须放在一个同步块中。
  • 也许是因为在示例中他需要确保某些不属于实例成员的值受到保护免受竞争条件的影响,或者您的示例编码错误?
【解决方案3】:

让 ExecutorService 任务调用静态同步方法将成为瓶颈。一次只能有一个线程执行此方法。

如果 ExecutorService 中的所有任务都需要进行此调用,那么您将无法实现拥有多个线程的目的,因为大多数线程可能会花费时间等待获取类上的监视器,以便它们可以调用静态方法。

静态同步方法用于保护共享状态免受不安全的并发访问。为每个任务赋予自己的状态并尽可能消除共享比让所有线程轮流访问共享资源要好得多。

【讨论】:

  • 我明白了,所以如果我理解正确的话,如果我删除同步方法,瓶颈就会消失。
  • @James.Wyst:synchronized 关键字的存在可能是有充分理由的,您不想仅仅为了导致数据争用或其他线程安全问题而消除瓶颈。为每个任务提供自己的 httpclient 以进行调用,并为其提供自己的数据以进行处理。
猜你喜欢
  • 1970-01-01
  • 2011-08-13
  • 2011-07-07
  • 2012-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 1970-01-01
相关资源
最近更新 更多