栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Java中同步String对象

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Java中同步String对象

快速浏览一下你所说的内容,而无需全神贯注,就好像你需要intern()你的Strings:

final String firstkey = "Data-" + email;final String key = firstkey.intern();

否则,两个具有相同值的字符串不一定是同一对象。

请注意,这可能会引入新的争用点,因为在VM的深处,intern()可能必须获取锁。我不知道现代虚拟机在这一领域会是什么样子,但有人希望可以对其进行优化。

我假设你知道StaticCache仍然需要是线程安全的。但是,如果你锁定缓存而不是调用getSomeDataForEmail时的密钥,那么与你的争用应该是很小的。

对问题更新的回复:

我认为这是因为字符串文字总是产生相同的对象。戴夫·科斯塔(Dave Costa)在评论中指出,这甚至比这更好:文字总是产生规范的表示形式。因此,程序中任何地方具有相同值的所有String文字都会产生相同的对象。

编辑

其他人指出,在内部字符串上进行同步实际上是一个糟糕的主意 -部分是因为允许创建内部字符串使它们永久存在,部分原因是,如果程序中任何位置的代码多于一个内部字符串,你在这些代码位之间有依赖性,并且防止死锁或其他错误可能是不可能的。

通过键入其他答案,正在开发通过为每个键字符串存储一个锁定对象来避免这种情况的策略。

这是一种替代方案-它仍然使用单数锁,但是我们知道无论如何我们都将需要其中一个用于缓存,而你正在谈论的是50个线程,而不是5000个线程,因此这可能不是致命的。我还假设这里的性能瓶颈是缓慢阻止DoSlowThing()中的I / O,因此将从未序列化中受益匪浅。如果这不是瓶颈,那么:

  • 如果CPU繁忙,则此方法可能不够用,你需要另一种方法。
  • 如果CPU不忙,并且对服务器的访问不是瓶颈,那么这种方法就显得过大了,你可能会忘记此锁定和按键锁定,并在整个操作过程中放置​​一个较大的sync(StaticCache),然后执行这是简单的方法。
    显然,在使用前需要对这种方法进行可伸缩性测试-我不保证。

此代码不要求StaticCache同步或以其他方式线程安全。如果任何其他代码(例如,计划中的旧数据清除)曾经接触过缓存,则需要重新考虑这一点。

IN_PROGRESS是一个伪值-并非完全干净,但是代码很简单,并且节省了两个哈希表。它不处理InterruptedException,因为我不知道你的应用在这种情况下想要做什么。同样,如果DoSlowThing()对于给定的键始终失败,则该代码本身并不十分优雅,因为每个线程都将重试它。由于我不知道失败标准是什么,也不知道它们是临时的还是永久的,因此我也不处理这种故障,我只是确保线程不会永远阻塞。在实践中,你可能希望将表示“不可用”的数据值放入高速缓存中,这可能是有原因的,以及何时重试的超时。

// do not attempt double-check locking here. I mean it.synchronized(StaticObject) {    data = StaticCache.get(key);    while (data == IN_PROGRESS) {        // another thread is getting the data        StaticObject.wait();        data = StaticCache.get(key);    }    if (data == null) {        // we must get the data        StaticCache.put(key, IN_PROGRESS, TIME_MAX_VALUE);    }}if (data == null) {    // we must get the data    try {        data = server.DoSlowThing(key);    } finally {        synchronized(StaticObject) { // WARNING: failure here is fatal, and must be allowed to terminate // the app or else waiters will be left forever. Choose a suitable // collection type in which replacing the value for a key is guaranteed. StaticCache.put(key, data, CURRENT_TIME); StaticObject.notifyAll();        }    }}

每次将任何内容添加到缓存中时,所有线程都将唤醒并检查缓存(无论它们使用的是什么键),因此可以使用较少争议的算法来获得更好的性能。但是,大部分工作将发生在I / O上的大量空闲CPU时间阻塞期间,因此这可能不是问题。

如果为高速缓存及其关联的锁定义了合适的抽象,它返回的数据,IN_PROGRESS伪指令以及执行缓慢的操作,则该代码可能会与多个高速缓存一起使用。将整个过程都放入缓存中的方法可能不是一个坏主意。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/514634.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号