Java 将线程安全委托给ConcurrentMap和AtomicInteger

Java 将线程安全委托给ConcurrentMap和AtomicInteger,java,multithreading,Java,Multithreading,我需要提供以下容器的线程安全实现: public interface ParameterMetaData<ValueType> { public String getName(); } public interface Parameters { public <M> M getValue(ParameterMetaData<M> pmd); public <M> void put(ParameterMetaData<

我需要提供以下容器的线程安全实现:

public interface ParameterMetaData<ValueType> {
    public String getName();
}

public interface Parameters {
    public <M> M getValue(ParameterMetaData<M> pmd);
    public <M> void put(ParameterMetaData<M> p, M value);
    public int size();
}
问题是,我不能只调用
ConcurrentHashMap
实例上的
parameters.size()
来返回实际大小,因为操作执行遍历时没有锁定,并且无法保证它将检索实际大小。这对我来说是不可接受的。因此,我决定维护包含大小的字段


问题:是否有可能以某种方式授权线程安全并保留不变量?

您想要实现的结果是非原子的。您希望修改映射,然后获得在单个线程范围内保持一致的元素数。实现这一点的唯一方法是通过同步对映射的访问使该流成为“原子操作”。这是确保计数不会因在另一个线程中进行的修改而改变的唯一方法

通过
synchronized
Semaphore
同步对映射的修改计数访问,以仅允许单个线程同时修改映射和计数元素

在这里使用附加字段作为计数器并不能保证线程安全,因为在映射修改之后和计数器操作之前,其他线程实际上可以修改映射,并且计数器值将无效

这就是为什么map不在内部保持其大小,而是必须遍历元素,以便在给定的时间点提供最准确的结果

编辑: 100%清楚地说,这是实现这一目标最方便的方法:

synchronized(yourMap){
    doSomethingWithTheMap();
    yourMap.size();
}

因此,如果您将每个映射操作更改为这样的块,您将保证
size()
将返回元素的准确计数。唯一的条件是所有数据操作都是使用这种同步块完成的。

您想要实现的结果是非原子的。您希望修改映射,然后获得在单个线程范围内保持一致的元素数。实现这一点的唯一方法是通过同步对映射的访问使该流成为“原子操作”。这是确保计数不会因在另一个线程中进行的修改而改变的唯一方法

通过
synchronized
Semaphore
同步对映射的修改计数访问,以仅允许单个线程同时修改映射和计数元素

在这里使用附加字段作为计数器并不能保证线程安全,因为在映射修改之后和计数器操作之前,其他线程实际上可以修改映射,并且计数器值将无效

这就是为什么map不在内部保持其大小,而是必须遍历元素,以便在给定的时间点提供最准确的结果

编辑: 100%清楚地说,这是实现这一目标最方便的方法:

synchronized(yourMap){
    doSomethingWithTheMap();
    yourMap.size();
}

因此,如果您将每个映射操作更改为这样的块,您将保证
size()
将返回元素的准确计数。唯一的条件是所有数据操作都是使用这种同步块完成的。

如果没有外部锁定,您无法获得比ConcurrentHashMap已经提供的更高的精度,因为您无法保证原子操作。如果没有外部锁定,您无法获得比ConcurrentHashMap已经提供的更高的精度,由于您无法保证原子操作。顺便说一句,notThreadSafe HashMap通过将其存储在字段中,在内部跟踪大小。所以,在某种程度上,唯一的方法是应用监控模式并同步所有内容,对吗?因此,不需要使用当前映射和大小计数器。HashMap会运行得很好。这就是为什么它是NTS:)如果您将使用
synchronized
块访问映射并读取计数,那么它将通过TS执行,并且计数将是准确的。但是,如果您只同步映射操作方法并在同步范围之外调用
getSize()
,这仍然是NTS,并且不能保证一致性。好的,明白了,非常感谢。但在检索大小时,HashMap不会执行遍历,这可靠吗?或者更安全的做法是自己记录尺寸,将其划入一块场地?@St.Antario为了加快速度(但可能你不必为小地图这样做),你可以自己记录元素,以便随时阅读。@St.Antario这就是我的意思。顺便说一句,notThreadSafe HashMap通过将其存储在字段中,在内部跟踪大小。所以,在某种程度上,唯一的方法是应用监控模式并同步所有内容,对吗?因此,不需要使用当前映射和大小计数器。HashMap会运行得很好。这就是为什么它是NTS:)如果您将使用
synchronized
块访问映射并读取计数,那么它将通过TS执行,并且计数将是准确的。但是,如果您只同步映射操作方法并在同步范围之外调用
getSize()
,这仍然是NTS,并且不能保证一致性。好的,明白了,非常感谢。但在检索大小时,HashMap不会执行遍历,这可靠吗?或者更安全的做法是自己记录尺寸,将其划入一块场地?@St.Antario为了加快速度(但可能你不必为小地图这样做),你可以自己记录元素,以便随时阅读。@St.Antario这就是我的意思。但你可以做到。