【问题标题】:Java : one lock per method per objectJava:每个对象每个方法一个锁
【发布时间】:2016-01-14 12:56:33
【问题描述】:

我正在构建一个网络爬虫,它有 2 个主要功能,它们都作为线程执行: - 提取器(抓取网站并将文件中的单独链接存储到数据库中)。 - 下载器(根据 fetcher 返回的 url 下载文件)。

我有一个对象WebSite,其中包括我想了解的有关网站的所有信息。现在我想操作我的数据库,将链接的状态从 waiting 更改为 fetching,然后再更改为 fetched。从等待正在下载再到已下载的文件也是如此。

为了防止 Fetcher 获取已被另一个提取器选择的链接,我在 WebSite 对象中完成了此功能:

public synchronized String[] getNextLink(){
    //Return the next link from database that has visited set to 0 then change it to -1 to say that it's in-use.
}

我用这个函数为我的Downloaders 做了同样的事情:

public synchronized String getNextFile(){
    //Return the next file from database that has downloaded set to 0 then change it to -1 to say that it's downloading
}

这两种方法都在我的 WebSite 对象中,因为如果 2 个 Fetchers 正在使用不同的网站,他们无法在我的数据库中选择同一行(下载器也是如此)。但是可以同时调用这两个函数,因为Fetchers 永远不会选择文件,而Downloaders 永远不会选择链接

现在 同步 使用单个锁(每个对象),因此我的两个方法不能同时调用。是否有另一个关键字可以使用每个对象每个方法一个锁?还是我需要编码?

【问题讨论】:

  • 为什么还需要同步?难道你不应该确保每个WebSite 都被一个Downloader 和一个Fetcher 处理吗?
  • 我希望多个下载器使用同一个网站同时下载来自该网站的多个文件。 Fetcher 也是如此,可以更快地抓取网站。

标签: java multithreading concurrency synchronized


【解决方案1】:

您可以使用两个独立的锁对象(any 对象可以用作Java 中的 lock-object)在方法中。每个锁对象都将独立于其他对象:

private final Object fetcherMutex = new Object();
private final Object downloaderMutex = new Object();

public String[] getNextLink(){
    synchronized (fetcherMutex) { /* ...  */ }
}

public String[] getNextFile(){
    synchronized (downloaderMutex) { /* ...  */ }
}

【讨论】:

  • 由于我的两个方法都在一个对象内部,在我的对象内部创建 2 个锁并自己处理它们不是比实例化 2 个将具有 JVM 提供的锁的对象更快吗?
  • 为了防止意外,你应该将锁声明为final,即。 final Object fetcherMutex = new Object();
  • @Palamino 感谢 - 添加了 privatefinal 修饰符
  • @naurel 正如您所建议的那样,这两个锁将在您的类中声明。所有 java 对象都可以用作锁,无论您是否这样做 - 您无需为“创建将用作锁的对象”与“创建锁”支付任何额外费用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
相关资源
最近更新 更多