多个字段: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 theConcurrentHashMap<Id,AtomicReference<Shared>>
is viable or wrong or just superfluous. Anyone can explain? thanks!
原文:https://stackoverflow.com/questions/21283293
最满意答案
这是一个使用
Enumerable
类ToLookup
,All
,Count
和Any
扩展方法的更简洁的实现(我会让你决定它是否更具可读性):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
classToLookup
,All
,Count
andAny
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 toGroupBy
, but creates a reusable data structure (because we'll need 2 passes).Then
from.All(g => g.Count() == to[g.Key].Count())
checks if everyFrom
has correspondingTo
and their counts match. Note that in case the key doesn't exist, theILookup<TKey, TElement>
indexer does not throw exception or returnnull
, but returns an emptyIEnumerable<TElement>
, which allows us to combine the checks.Finally the
to.All(g => from[g.Key].Any())
checks if everyTo
has correspondingFrom
. 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 ...
-
什么是面向数据的设计?(What is data oriented design?)[2023-03-19]
首先不要将此与数据驱动设计混淆。 我对数据导向设计的理解是关于组织数据进行有效的处理。 特别是关于缓存未命中等等。另一方面,数据驱动设计就是让数据控制很多你的程序行为(由Andrew Keith的回答描述得很好)。 假设你的应用程序中有球形对象,其颜色,半径,圆度,位置等属性。 面向对象的方法 在OOP中,你会像这样描述你的球: class Ball { Point position; Color color; double radius; void draw(); }; 然后你会创 ... -
R中的螺旋图(Spiral Graph in R)[2023-04-20]
为了检查周期性, 循环图 (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, ... -
我的纱线以哪种方式为导向?(Which way is my yarn oriented?)[2022-06-29]
您可能会尝试在频域中执行此操作。 傅立叶变换的输出取决于方向,因此,如果您有某种定向模式,则可以应用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力导向图(JUNG force directed graph)[2023-07-13]
看起来你正在寻找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.
-
平衡导向图(Balancing oriented graph)[2023-08-06]
这是一个使用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 ... -
检查简单的图形是否面向?(Check if simple graph is oriented?)[2021-11-01]
我不知道它是否真的是一个问题,但如果你的输出应该是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 ...