当前位置: 首页 > 知识库问答 >
问题:

Java - 同步对象/块

冷善
2023-03-14

我正在寻找有关同步块的澄清。考虑一下这个类 -

public class A{
Map map;

 public getValue(String key){
  return map.get(key);
 }

 public remove(String key){
  synchronized(map){
   map.remove(key);
  }
 }
}

A是单例。getValue在整个应用程序中被多个线程大量访问。我添加了一个新方法remove,它从映射中删除一个键。如果如上所述执行删除,

  1. 当线程位于remove方法的同步块中时,我假设它将获取map对象上的锁。这是否意味着其他试图通过getValue方法访问映射的线程将被阻止?(我希望他们这样做。)
  2. 当remove方法的同步块中没有线程时,访问getValue方法的线程是否会正常工作,即不会相互阻塞?(我也很喜欢)

我希望只有当有线程执行删除操作时,才会阻塞 getValue 线程。

共有3个答案

尉迟雅昶
2023-03-14

您没有展示Map实例是如何实例化的,但是假设它不是线程安全的集合实例,那么这段代码就不是线程安全的。

商开宇
2023-03-14

如果我正确理解了您的需求,您可以看看ConcurrentMap,当然还有Concurrent HashMap,我认为它是随Java 5.0引入的,支持一定程度的并发性。

裴泰平
2023-03-14

当线程位于remove方法的同步块中时,我假设它将获取map对象上的锁。这是否意味着其他试图通过getValue方法访问映射的线程将被阻止?

不。这意味着你有一个问题,除非你碰巧使用的是线程安全的映射实现。

当删除方法的同步块中没有线程时,访问getValue方法的线程是否像往常一样起作用,即不相互阻塞?(我也想要)。

它们不会相互阻塞,不会。同样,您需要确保您正在使用的任何Map实现都可以,尽管它比在编写的同时阅读更有可能是可以的。

您应该考虑使用ConcurrentMap实现(例如Concurrent HashMap),此时您根本不需要任何同步。

如果您不能使用它,我建议在getValueremove中同步,并测量性能。获取一个无争用的锁相当便宜——你真的需要无锁吗?(当然,使用ConcurrentHashMap是避免问题的一种相当简单的方法,但在开始微优化之前,您应该始终考虑是否需要额外的复杂性来实现所需的性能。)

 类似资料:
  • 在示例代码中 在这个页面上, lock1和lock2分别控制c1和c2上的更新。 然而, 正在获取对象lock1的锁并在同步块时释放它 被执行。 当这个代码块被执行时,这个对象的成员c1上可能还有一个更新——我看不出这个更新是如何被代码中的lock1上的同步所阻止的。 只有对象lock1可以独占访问——除此之外别无它物(?) 那么,实施情况如何 在上面的代码中不同于 甚至 当c1是一个对象而不是一

  • 问题内容: 我有一个Web应用程序正在进行负载/性能测试,特别是在一项功能上,我们希望数百名用户正在访问同一页面,并且每10秒刷新一次。我们发现可以使用此功能进行改进的一个方面是,由于数据未更改,因此将Web服务的响应缓存了一段时间。 在实现了基本的缓存之后,在进一步的测试中,我发现我没有考虑并发线程如何同时访问缓存。我发现在大约100毫秒内,约有50个线程试图从缓存中获取对象,发现对象已过期,点

  • 假设我有两条线。Thread1正在访问一个同步方法,同时,Thread2正在访问同一对象的另一个同步方法。据我所知,Thread2应该等到Thread1完成它的任务。我的问题是,Thread2是否在对象的等待线程列表中?对我来说似乎是这样,但Thread2不调用wait()方法,那么作为逻辑结果,它不应该在对象的等待线程列表中。如果它不在对象的等待线程列表中,那么Thread2的状态是什么?

  • 我想基于输入参数同步一个方法或一个块。 因此,我有一个API,它在post有效负载中有两个长类型的输入(比如id1和id2),可以是原始的,也可以是包装的),可以是JSON。这个API将被多个线程同时或随机地在不同时间调用。 现在如果第一个API调用有ID1=1和ID2=1,同时另一个API调用有ID1=1和ID2=1,它应该等待第一个API调用处理完毕后再执行第二个调用。如果第二个API调用具有

  • 我试图理解java中同步块的概念。根据我读过的文档,我明白如果我们获取一个锁(使用实例变量的同步块),那么我们就不能在该类中的同一对象上获取同步锁。但是当我尝试实际使用以下片段时,我发现我的理解出了问题。 即我能够同时以两种不同的方法获取锁(同一实例变量上的同步块)。当线程启动时,它将转到run方法并无限期地等待,并且不会从同步块中出来。同时,如果我使用相同的线程调用stop方法,它会进入同步块并

  • 问题内容: 代码段-1 代码段-2 我在第一个代码段中遇到了竞争。我知道这是因为我正在获得对不可变对象(类型为Integer)的锁定。 我已经写了第二个代码片段,这再次使“布尔”不变。但这有效(输出运行中不显示竞争条件)。如果我正确理解了上一个问题的解决方案,则以下是出现问题的一种可能方法 线程1锁定由指向的对象(例如A) 线程2现在试图获取由指向的对象的锁,并进入A的等待队列。 线程1进入同步块