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

喜欢同步而不是不稳定

蒙弘图
2023-03-14

我读了这个答案,最后写了以下内容:

任何你可以用易失性来完成的事情都可以用同步来完成,但反之亦然。

不清楚。JLS8.3.1.4定义易失性字段如下:

一个字段可以被声明为易失性的,在这种情况下,Java内存模型确保所有线程看到变量的一致值(§17.4)。

所以,易失性字段是关于内存可见性的。此外,就我引用的答案而言,对不稳定字段的读写是同步的。

同步,进而保证只有一个线程可以访问同步块。据我所知,这与记忆可见度无关。我错过了什么?

共有3个答案

段渊
2023-03-14

如果多个线程写入一个共享的易失性变量,并且它们还需要使用该变量的前一个值,则可能会创建竞争条件。所以在这一点上,你需要使用同步。

... 如果两个线程都在读写一个共享变量,那么仅使用volatile关键字是不够的。在这种情况下,需要使用synchronized来保证变量的读写是原子的。读取或写入可变变量不会阻止线程读取或写入。要实现这一点,必须在关键部分周围使用synchronized关键字。

有关挥发性的详细教程,请参阅“挥发性”并不总是足够的。

颛孙正谊
2023-03-14

Synchronized和volatile是不同的,但通常它们都用于解决相同的常见问题。

同步是确保在给定时间点只有一个线程将访问共享资源。

然而,这些共享资源通常被声明为不稳定的,这是因为,如果一个线程更改了共享资源的值,那么它也必须在另一个线程中更新。但如果没有volatile,运行时只需通过从缓存中读取值来优化代码。所以volatile的作用是,每当任何线程访问volatile时,它都不会从缓存中读取值,而是从实际内存中获取值,并使用相同的值。

正在查看log4j代码,这就是我发现的。

/**
 * Config should be consistent across threads.
 */
protected volatile PrivateConfig config;
程振濂
2023-03-14

事实上,同步也与内存可见性有关,因为JVM在同步块的出口增加了一个内存屏障。这确保了同步块中的线程的写入结果在第一个线程退出同步块后,通过另一个线程的读取保证可见。

注意:在@PaŭloEbermann的评论之后,如果另一个线程通过读内存障碍(例如通过进入同步块),它们的本地缓存不会失效,因此它们可能会读取旧值。

在本文档中,同步块的退出是一个先发生后发生的情况:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility

寻找这些提取物:

只有在写操作发生在读操作之前,一个线程的写操作的结果才能保证对另一个线程的读操作可见。

而且

监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法进入)之前。由于“发生在之前”关系是可传递的,因此在解锁之前线程的所有操作都发生在监视的任何线程锁定之后的所有操作之前。

 类似资料:
  • 问题内容: 当喜欢过? 何时以及何时使用哪种数据结构: 您想要高效的读写 应该具有更少的内存占用 尽管存在类似的问题,但它并没有突出表明应该优先选择哪个事实? 问题答案: 蜘蛛侠鲍里斯(Boris the Spider)已经概述了和之间最明显的区别-前者始终是有界的,而后者可以是无界的。 因此,如果您需要无限制的阻塞队列,或者将其用作工具箱中的最佳选择。 但是,假设您需要一个有限的阻塞队列。最后,

  • 问题内容: 我的要求是仅显示跨数据库从数据库检索的一组值。我正在使用jQuery。 问题答案: 如果满足以下任一条件,则将XML优先于JSON: 您需要消息验证 您正在使用XSLT 您的消息中包含很多标记文字 您需要与不支持JSON的环境进行互操作 当所有这些都成立时,在XML上偏爱JSON: 不需要验证消息,或者验证消息的反序列化很简单 您不是要转换邮件,也不是转换邮件的反序列​​化很简单 您的

  • 我在PostgresQL中有一个表feed_item_likes_dislikes(feed_item_id,user_id,vote),其中 feed_item_id是uuid 用户id为整数 投票=正确那么这是一个类似 投票=FALSE那么这是一种厌恶 vote=NULL表示用户最初喜欢或不喜欢,但通过取消通知返回并删除了投票 我还有另一个表feed_item_likes_dislikes_a

  • 问题内容: 是否可以在一个查询中将多个SQL LIKE通配符串在一起-像这样? 目的是查找同时包含通配符但没有特定顺序的记录。 问题答案: 正确的SQL语法是:

  • 喜欢资讯 取消喜欢资讯 资讯喜欢列表 喜欢资讯 POST /news/{news}/likes Response Headers Status: 201 Created 取消喜欢资讯 DELETE /news/{news}/likes Response Headers Status: 204 No Content 资讯喜欢列表 GET /news/{news}/likes Respons

  • 点喜欢 取消喜欢 喜欢的人列表 点喜欢 POST /feeds/:feed/like Response Status: 201 Created { "message": [ "操作成功" ] } 通知类型 { "channel": "feed:digg", // 通知关键字 "target": 325, // 动态id "content": "@2222 点喜欢了