首页 \ 问答 \ 多个字段:volatile还是AtomicReference?(multiple fields: volatile or AtomicReference?)

多个字段:volatile还是AtomicReference?(multiple fields: volatile or AtomicReference?)

我必须将线程之间的访问同步到共享对象,共享对象的状态由多个字段组成。 说:

class Shared{
String a; Integer b;
//constructor, getters and setters
....
}

我可能有很多线程正在阅读这些对象

//readers
shared.getA();
shared.getB();

并且只有一个线程会在某个点写入:

//writer
shared.setA("state");
shared.setB(1);

现在我的问题是如何确保读取线程不会在不一致的状态下找到共享对象。

我读了许多答案,说为了线程之间的一致性, volatile是解决方案,但我不确定它在多个字段上是如何工作的。 就是这样够了吗?

volatile  String a; volatile Integer b;

另一个解决方案是使共享对象不可变并使用AtomicReference,例如,

AtomicReference<Shared> shared = ....

然后作者将交换参考:

Shared prev = shared.get(); 
Shared newValue = new Shared("state",1);
while (!shared.compareAndSet(prev, newValue)) 

这种方法是否正确? 谢谢!

更新在我的设置中,共享对象是从ConcurrentHashMap<Id,Shared>中检索的,因此注释同意要采用不可变方法或通过同步共享所有更新来实现。 但是,为了完整性,很高兴知道上面使用ConcurrentHashMap<Id,AtomicReference<Shared>>的解决方案是可行的还是错误的还是多余的。 谁能解释一下? 谢谢!


I have to synchronize access between threads to a shared object, whose state consists of several fields. Say:

class Shared{
String a; Integer b;
//constructor, getters and setters
....
}

I have possibly many threads reading this objects, doing

//readers
shared.getA();
shared.getB();

and only one thread that will write at a certain point:

//writer
shared.setA("state");
shared.setB(1);

now my question is how to ensure that reading threads won't find the shared object in an inconsistent state.

I read many answers saying that for consistency between threads volatile is the solution,but I'm not sure how it works on multiple fields. E.g., is that enough?

volatile  String a; volatile Integer b;

Another solution would be to make the shared object immutable and use AtomicReference, E.g.,

AtomicReference<Shared> shared = ....

and then the writer will just swap the reference:

Shared prev = shared.get(); 
Shared newValue = new Shared("state",1);
while (!shared.compareAndSet(prev, newValue)) 

Is that approach correct? thanks!

Update In my setting the Shared objects are retrieved from a ConcurrentHashMap<Id,Shared>, so the comments agree that the way to go is either using the immutable approach or via synchronizing the updates on shared all together. However, for completeness would be nice to know whether the solution above with the ConcurrentHashMap<Id,AtomicReference<Shared>> is viable or wrong or just superfluous. Anyone can explain? thanks!


原文:https://stackoverflow.com/questions/21283293
更新时间:2024-02-13 10:02

最满意答案

这是一个使用EnumerableToLookupAllCountAny扩展方法的更简洁的实现(我会让你决定它是否更具可读性):

public static bool IsGraphBalanced<T>(List<Edge<T>> edges)
{
    var from = edges.ToLookup(e => e.From);
    var to = edges.ToLookup(e => e.To);
    return from.All(g => g.Count() == to[g.Key].Count())
        && to.All(g => from[g.Key].Any());
}

ToLookup方法类似于GroupBy ,但创建了可重用的数据结构(因为我们需要2次传递)。

然后从from.All(g => g.Count() == to[g.Key].Count())检查每个From是否具有相应的To并且它们的计数是否匹配。 请注意,如果密钥不存在, ILookup<TKey, TElement>索引器不会抛出异常或返回null ,而是返回一个空的IEnumerable<TElement> ,这允许我们组合这些检查。

最后, to.All(g => from[g.Key].Any())检查每个To是否有相应的From 。 此处无需检查计数,因为已在上一步中检查过计数。


Here is a more concise implementation utilizing Enumerable class ToLookup, All, Count and Any extension methods (I'll let you decide whether it's more readable or not):

public static bool IsGraphBalanced<T>(List<Edge<T>> edges)
{
    var from = edges.ToLookup(e => e.From);
    var to = edges.ToLookup(e => e.To);
    return from.All(g => g.Count() == to[g.Key].Count())
        && to.All(g => from[g.Key].Any());
}

The ToLookup method is similar to GroupBy, but creates a reusable data structure (because we'll need 2 passes).

Then from.All(g => g.Count() == to[g.Key].Count()) checks if every From has corresponding To and their counts match. Note that in case the key doesn't exist, the ILookup<TKey, TElement> indexer does not throw exception or return null, but returns an empty IEnumerable<TElement>, which allows us to combine the checks.

Finally the to.All(g => from[g.Key].Any()) checks if every To has corresponding From. There is no need to check the counts here because they have been checked in the previous step.

相关问答

更多
  • 在Cassandra中,每一行(由一个键寻址)都包含一个或多个“列”。 列本身是键值对。 列名不需要预定义,即结构不是固定的。 一行中的列按照它们的键(名称)的排序顺序存储。 在某些情况下,您可能在行中有非常多的列数(例如,作为启用特定类型查询的索引)。 Cassandra可以有效地处理这样大的结构,并且可以检索特定范围的列。 有一个称为超级列的结构(不常用)的其他级别,其中列包含嵌套(子)列。 您可以将整体结构视为嵌套散列表/字典,具有2或3级密钥。 正常列族: row col col col ...
  • 首先不要将此与数据驱动设计混淆。 我对数据导向设计的理解是关于组织数据进行有效的处理。 特别是关于缓存未命中等等。另一方面,数据驱动设计就是让数据控制很多你的程序行为(由Andrew Keith的回答描述得很好)。 假设你的应用程序中有球形对象,其颜色,半径,圆度,位置等属性。 面向对象的方法 在OOP中,你会像这样描述你的球: class Ball { Point position; Color color; double radius; void draw(); }; 然后你会创 ...
  • 为了检查周期性, 循环图 (pdf)很好地工作。 用于分析时间序列的周期性的功能也很多。 从xts包中的stl和periodicity开始。 使用ggplot2 ,你可以像这样创建一个螺旋图: library(ggplot2) data(beavers) p <- ggplot(beaver1, aes(time, temp, colour = day)) + geom_line() + coord_polar(theta = "x") p For examining periodicity, ...
  • 您可能会尝试在频域中执行此操作。 傅立叶变换的输出取决于方向,因此,如果您有某种定向模式,则可以应用2D FFT,并且您将看到围绕特定方向的聚类。 例如,将图像灰度化并执行FFT(使用ImageJ)可以实现: 您可以看到一个与纱线方向正交的独特簇。 通过对源图像进行一些预处理,为了消除噪声并增强面向特性,您可能会在FFT中获得更强的信号。 一旦你有了一个簇,你可以使用类似PCA的东西来确定主轴的向量。 有关信息,这是一种常用于增强面向特征(如指纹)的技术,方法是在FFT中应用选择性滤波器,然后取反,以获得更 ...
  • 在有向图中,入站和出站边必须相同: http : //www8.cs.umu.se/kurser/TDBAfl/VT06/algorithms/BOOK/BOOK4/NODE165.HTM In a directed graph the inbound and outbound edge must be the same:http://www8.cs.umu.se/kurser/TDBAfl/VT06/algorithms/BOOK/BOOK4/NODE165.HTM
  • 我将此模式用于基于NHibernate的项目: public interface IRepository : IQueryable { T Get(int id); void Save(T item); void Delete(T item); } public class NHibernateRepository : IRepository where ModelType : class { // impl ...
  • 看起来你正在寻找jung-1.x文档。 在jung-2.x DirectedSparseGraph是一个泛型类,其顶点V和边E类型参数。 这也是使用任意属性定义顶点和边的方法。 例如,如果要使用边权重,请创建一个具有权重的合适边缘类: class Edge { public double weight; } 请注意,您通常还希望至少为顶点实现equals()和hashCode() 。 如果要使用权重进行布局(例如,在SpringLayout , 其中一个构造函数采用lengthFunc ...
  • 每个节点都有可以映射到对象字段的属性。 您可以手动执行此操作,也可以使用spring-data进行映射。 Each node has attributes that can be mapped to object fields. You can do that manually, or you can use spring-data to do the mapping.
  • 这是一个使用Enumerable类ToLookup , All , Count和Any扩展方法的更简洁的实现(我会让你决定它是否更具可读性): public static bool IsGraphBalanced(List> edges) { var from = edges.ToLookup(e => e.From); var to = edges.ToLookup(e => e.To); return from.All(g => g.Count() == t ...
  • 我不知道它是否真的是一个问题,但如果你的输出应该是YES或NO你最好打印这些而不是Yes和No这里System.out.println((truth)? "Yes": "No"); 。 PS如果你的图形有一个从顶点到同一个图形的方式(我的意思是matrix[i][i] = 1 ),你的算法可能会认为图形是无向的,而不是。 I don't know if it is actually a problem, but if your output should be YES or NO you'd better ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。