- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个(大约 250.000)个三态单元,其状态为 UNKNOWN、TRUE 或 FALSE。
所有单元格均以 UNKNOWN 开头。然后一组大约 60 个线程(在 AMD ThreadRipper 64 核 CPU 上)进行计算并将这些变量从 UNKNOWN 设置为 TRUE 或 FALSE。
一旦为单元格分配了值,它就永远不会改变。
如果两个线程通过不同的策略独立地计算出单元格的值应该是什么,则同一个值可能会被分配给一个单元格两次。线程稍后“稍微”看到单元格的更改并不重要。如果另一个线程决定将 TRUE 分配给值为 UNKNOWN 的单元格,则它绝不能看到中间值 FALSE。反之亦然。
线程越早看到单元格的更改就越好。在这些条件下,我也不关心写入重新排序。
我目前正在使用 AtomicInteger
来实现单元。分析显示,我在这门课上花费了大约 30% 的计算时间。
我可以做些什么来改善这种情况?
PS。我这样做是为了创建一个 Nonogram 解算器。最佳答案
正如我们在德国所说的“Einen Tod muss mann sterben”,因此无法绕过某种锁定或同步。
volatile 不能满足您的要求。
考虑这种情况:
这种情况有些人为,但有可能,并且按照您正在进行的数字运算,很有可能。这就是墨菲定律。
多个线程可以从 volatile 中读取正确的值是不够的,它们需要确保状态在更新期间保持不变,这就是为什么没有办法绕过某种锁定。
另请注意,广泛传播的双重检查锁定算法(至少在 Java 中)是一种被误解的反模式。它会失败。您可以在维基百科中阅读相关内容。
尝试下面的概念验证程序。
它使用同步来解决您的需求并且坚如磐石。
性能:90 秒内 10 亿次访问,多线程。
import java.security.SecureRandom;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class TriState {
private static final byte TRI_STATE_UNKNOWN = 0;
private static final byte TRI_STATE_TRUE = 1;
private static final byte TRI_STATE_FALSE = 2;
private byte value = TRI_STATE_UNKNOWN;
public synchronized boolean isUnknown() {
return value == TRI_STATE_UNKNOWN;
}
public synchronized boolean isTrue() {
return value == TRI_STATE_TRUE;
}
public synchronized boolean isFalse() {
return value == TRI_STATE_FALSE;
}
public synchronized boolean doIfKnown(final Runnable runnable) {
if (value != TRI_STATE_UNKNOWN) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean doIfUnknown(final Runnable runnable) {
if (value == TRI_STATE_UNKNOWN) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean doIfNotTrue(final Runnable runnable) {
if (value != TRI_STATE_TRUE) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean doIfTrue(final Runnable runnable) {
if (value == TRI_STATE_TRUE) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean doIfNotFalse(final Runnable runnable) {
if (value != TRI_STATE_FALSE) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean doIfFalse(final Runnable runnable) {
if (value == TRI_STATE_FALSE) {
runnable.run();
return true;
} else {
return false;
}
}
public synchronized boolean setTrue() {
/*
* ok to set True if its Unknown or already True...
*/
if (value != TRI_STATE_FALSE) {
value = TRI_STATE_TRUE;
return true;
} else {
return false;
}
}
public synchronized boolean setFalse() {
/*
* ok to set False if its Unknown or already False ...
*/
if (value != TRI_STATE_TRUE) {
value = TRI_STATE_FALSE;
return true;
} else {
return false;
}
}
private static final int SIZE = 250_000;
private static final TriState[] TRI_STATE = IntStream.range(0, SIZE).mapToObj(move -> new TriState()).toArray(TriState[]::new);
public static void main(final String[] args) throws Exception {
final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final SecureRandom rng = new SecureRandom();
final Duration duration = Duration.ofSeconds(90);
final Instant end = Instant.now().plus(duration);
/*
* Following accessed TRI_STATE 1,061,946,535 times in 90 seconds on a midrange Office PC...
*/
pool.submit(() -> {
while (Instant.now().isBefore(end)) {
Arrays.stream(TRI_STATE).forEach(triState -> {
if (rng.nextBoolean()) {
triState.setTrue();
} else {
triState.setFalse();
}
});
}
});
pool.shutdown();
pool.awaitTermination(duration.getSeconds(), TimeUnit.SECONDS);
}
}
这里有一个例子来强调为什么 volatile 会失败:
public boolean setTrue() {
/*
* Read out Status & if already set, we lost...
*/
if (status != UNKNOWN) {
return false;
}
/*
* Status is Unknown here & just BEFORE doing the following, another Thread reads out Status.
*/
/**/ status = TRUE; // Update volatile Status
/*
* Now we can detect if that Thread modifies Status between these 2 lines of code...
*/
return status == TRUE; // Is volatile Status still True?
/*
* Just AFTER doing the above, that Thread updates Status to False, thinking its Unknown.
*
* So now both Threads think they won & you are up a certain creek without a paddle!
*/
}
关于Java多线程: Fast alternative to AtomicInteger wanted,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59579772/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我正在使用 gradle 1.4,并将 build.gradle 重命名为 buildExpr.gradle,将 settings.gradle 重命名为 settingExpr.gradle,这两个
使用 Ubuntu 16.04.7 我试图将 python3.8 作为我的默认 python 版本。我按照 here 给出的说明进行操作,但最终标准 python 版本没有改变。每当我运行 pytho
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 6年前关闭。 Improve this questi
我有一个函数,它对其参数进行模式匹配,以在 StateT () Maybe () 中生成计算。这个计算在运行时可能会失败,在这种情况下,我希望当前的模式匹配分支失败,可以这么说。 我非常怀疑是否可能有
我知道这类问题已经回答过几次,但我给出了问题的上下文以期待一些其他的架构替代方案。 考虑一个 CExpression 类: class CExpression { public:
当我的红色、绿色或蓝色变量发生变化时,我正在尝试使用 Combine 来更新颜色。我看过的示例使用 sink() ,这似乎适合我,但 eraseToAnySubscriber 是 MIA,我找不到替代
最近我不得不搜索一些字符串值来查看哪个匹配某个模式。在用户输入搜索词之前,字符串值的数量和模式本身都不清楚。问题是我注意到每次我的应用程序运行以下行时: if (stringValue.mat
我希望制作包含类对象列表的类对象的深拷贝,每个类对象都有自己的一组内容。对象不包含比整数和列表更令人兴奋的东西(没有字典,没有等待生成的生成器等)。我在一个循环中对 500-800 个对象执行深度复制
我正在尝试在表格中插入一个简单的行。有人可以指出这里发生了什么吗? CREATE TABLE recommendation_engine_poc.user_by_category (
使用 Get-ChildItem | Get-Member 我可以看到对象的方法和属性。但是我如何看到例如的不同可能值属性?我可以用 Get-ChildItem | Where-Object {$_.
我有一个任务是编写简单的解析器生成器,所以我编写了类似 ANTLR 的语法并尝试解析像“foo:bar;”这样的简单文件,但得到了以下输出: [@0,0:2='foo',,1:0] [@1,3:3='
这个问题已经有答案了: Why order matters in this RegEx with alternation? (3 个回答) Order of regular expression op
Ax 2009 中的 MorphX 报表设计器似乎不是“最好的”报表设计器。我不知道是不是我的错,或者 morphx 报表设计器是否有太多错误而无法完成他的工作。我猜是否有一些替代方案可以为 Ax 2
除了 OWASP XSS 过滤软件之外,还有其他方法可以防止 XSS 攻击吗?如果可以在 apache 级别进行阻止,我需要建议。我不是安全专家,因此需要详细信息。感谢您的帮助 最佳答案 当数据向最终
在我的 Java EE 7 程序中,我想使用 @Alternative 根据上下文、生产或测试来注入(inject)不同的实现。我所做的就是在 beans.xml 文件中声明用 @Alternativ
我有一个文本文件,其中包含遵循替代模式的行,例如: name: SomeName counterA: 0, counterB: 0, counterC: 0 name: SomeNameB count
我知道标准的单例模式是这样的: 原创 public class Singleton1 { public static Singleton1 _Instance; public stat
在 Haskell 中,您可以像这样为临时变量创建 where 条件: f x | cond1 x = a | cond2 x = g a | otherwise = f (h x
我认为我能找到的所有适用于 Android 的自定义按钮教程都假设您使用三种图像作为按钮:普通图像、按下图像和聚焦图像。 不是本质上将给定按钮资源的大小增加三倍(并为美工/UX 人员创造更多工作),是
我是一名优秀的程序员,十分优秀!