我用GraphViz可视化一系列过程.每个进程都按程序顺序包含一些读或写操作.自然地,期望针对每个处理以从左到右的顺序布置操作.
使用GraphViz(版本2.28),我的代码如下:
digraph G
{
ranksep = 1.0; size = "10,10";
{
node [shape = plaintext, fontsize = 20];
0 -> 1 -> 2 -> 3 -> 4;
}
node [shape = box];
{rank = same;0;wy1;rf1;rc1;rz1;ry1;ra1;rb1;rx2;}
{rank = same;1;wf1;}
{rank = same;2;wx2;wc1;}
{rank = same;3;wf2;wz2;wx3;wa1;}
{rank = same;4;wz1;wy2;wx5;wb1;}
wy1 -> rf1;
rf1 -> rc1;
rc1 -> rz1;
rz1 -> ry1;
ry1 -> ra1;
ra1 -> rb1;
rb1 -> rx2;
wx2 -> wc1;
wf2 -> wz2;
wz2 -> wx3; …
Run Code Online (Sandbox Code Playgroud) 假设我有一个庞大的 Boolean
数组flags
:
Boolean[] flags = { true, false, true }; // 3 means "many"
Run Code Online (Sandbox Code Playgroud)
我想做两件事flags
:
true
返回并返回指标;false
.使用Java 8的lambda表达式,我可以按如下方式执行:
indicator = Arrays.stream(flags).allMatch(flag -> flag);
Arrays.stream(flags).forEach(flag -> flag = false);
return indicator;
Run Code Online (Sandbox Code Playgroud)
但是,此实现扫描flags
两次.由于flags
是巨大的,我不希望这样.另外,我更喜欢lambda方式.有没有办法checkIfAllTrueAndReset
用(单行)lambda表达式实现这种语义,flags
只扫描一次?
相关但不相同:检查布尔数组中的所有值是否为真的最优雅的方法是什么?
注意:我从评论和答案中学到了很多东西.谢谢你们!
Stream
很酷,但不是这个.BitSet
(以及它的位原子对应物AtomicBitSet
)更适合这种情况(因此被接受为答案;感谢其他人).map
(Stream
或通常是函数式编程)的副作用.Arrays.stream(flags).forEach(flag -> flag = false)
(在我的代码中)没有设置任何东西!在已知的论文"一个故障过程的分布式共识的不可能性"(JACM85)中,FLP(Fisher,Lynch和Paterson)证明了令人惊讶的结果,即没有完全异步的共识协议甚至可以容忍一个未宣布的过程死亡.
在引理3中,在显示D包含0价和1价配置之后,它说:
如果一个邻居在一个步骤中产生结果,则调用两个配置邻居.通过简单的归纳,存在邻域C 0,C1∈C,使得D 6 = e(C 6)是i价,i = 0,1.
我可以按照整个证据,除非他们声称存在这样的C 0和C 1.你能给我一些提示吗?
在下面的代码,当捕NumberFormatException
出来的for
迭代,以适当的形式字符串出现在strList
第一个错误的人之前(即"illegal_3"
)已成功解析(即,"1"
并"2"
已作为整数来分析1
和2
).
public void testCaughtRuntimeExceptionOutOfIteration() {
List<String> strList = Stream.of("1", "2", "illegal_3", "4", "illegal_5", "6").collect(Collectors.toList());
List<Integer> intList = new ArrayList<>();
try{
for (String str : strList) {
intList.add(Integer.parseInt(str));
}
} catch (NumberFormatException nfe) {
System.err.println(nfe.getMessage());
}
List<Integer> expectedIntList = Stream.of(1, 2).collect(Collectors.toList());
// passed
assertEquals("The first two elements have been parsed successfully.", expectedIntList, intList);
}
Run Code Online (Sandbox Code Playgroud)
然而,当更换for
的迭代stream()
或者parallelStream()
,我失去了1
和2
. …
Class clazz
有两种方法methodA()
和methodB()
.
methodB
如果某些线程methodA
在Java中(我使用的是Java 8),如何确保"被阻止" ?
通过"阻塞方法B",我的意思是"等到方法A()中没有线程".(感谢@AndyTurner)
请注意,上述要求允许以下情况:
methodA
.methodB
而没有线程methodA
.methodB
不会阻止其他线程进入methodA
.我的试用:我用StampedLock lock = new StampedLock
.
methodA
,打电话long stamp = lock.readLock()
unlockB
并调用lock.unlockRead(stamp)
它.methodB
,呼叫long stamp = lock.writeLock()
和lock.unlockWrite(stamp)
.但是,这种锁定策略不允许上述第二种和第三种情况.
编辑:我意识到我没有明确指出methodA
和之间的同步要求methodB
.@JaroslawPawlak给出的方法适用于当前的要求(我接受它),但不符合我的初衷(也许我应该首先澄清它,然后将其发布在另一个线程中).
Backgound:
在第3节,名为实施状态机,Lamport的论文Paxos Made Simple,Multi-Paxos被描述.Multi Paxos用于Google Paxos Made Live.(Multi-Paxos用于Apache ZooKeeper).在Multi-Paxos中,可能会出现差距:
通常,假设领导者可以
?
提前获得命令 - 也就是说,它可以在选择命令1到之后i + 1
通过i + ?
命令提出命令i
.? - 1
然后可能出现高达命令的差距.
现在考虑以下场景:
整个系统使用主从架构.只有主服务器提供客户端命令.Master和Slaves通过Multi-Paxos就命令序列达成共识.Master是Multi-Paxos实例的领导者.现在假设主服务器及其两个从服务器具有下图所示的状态(已选择命令):
.
请注意,主状态中存在多个间隙.由于不同步,这两个奴隶落后了.这时,主人失败了.
问题:
在检测到主设备故障后,从设备应该做什么(例如,通过心跳机制)?
特别是,如何处理与旧主人的差距和缺失的命令?
关于Zab的更新:
正如@sbridges指出的那样,ZooKeeper使用Zab而不是Paxos.报价,
Zab主要用于主备份(即主从)系统,如ZooKeeper,而不是用于状态机复制.
似乎Zab与我上面列出的问题密切相关.根据Zab的简短概述文件,Zab协议包括两种模式:恢复和广播.在恢复模式下,会做出两个特定的保证:永远不会忘记已提交的消息并放弃跳过的消息.我对Zab的困惑是:
- 在恢复模式下Zab是否也存在缺口问题?如果是这样,扎布做什么?
fault-tolerance distributed-computing paxos apache-zookeeper
码:
我有一个HashMap
private Map<K, V> map = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)
一种方法是通过调用将KV对放入其中put(K,V)
.
另一种方法想从其值中提取一组随机元素:
int size = map.size(); // size > 0
V[] value_array = map.values().toArray(new V[size]);
Random rand = new Random();
int start = rand.nextInt(size); int end = rand.nextInt(size);
// return value_array[start .. end - 1]
Run Code Online (Sandbox Code Playgroud)
这两个方法在两个不同的并发线程中调用.
错误:
我收到一个ConcurrentModificationException
错误:
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$ValueIterator.next(Unknown Source)
at java.util.AbstractCollection.toArray(Unknown Source)
Run Code Online (Sandbox Code Playgroud)
似乎toArray()
一个线程中的方法实际上是在HashMap上迭代,并且put()
在其他线程中发生了修改.
问题:如何在并发线程中使用HashMap.values().toArray()和HashMap.put()时避免"ConcurrentModificationException"?
直接避免values().toArray()
在第二种方法中使用也行.
java concurrency multithreading hashmap concurrentmodification
简而言之: collect(groupingBy())
返回一张地图Map<K, List<T>>
.我怎样才能更换,每个K
的价值List<T>
由(类新的值U
),这是基于计算的List<T>
,并返回Map<K, U>
在同一 stream()
?
一个例子:假设我有一个Task
,它由一个taskId
和一个Job
s列表组成:
public class Task { int taskId; List<Job> jobList; }
Run Code Online (Sandbox Code Playgroud)
对于每个Job
方法,方法getAgentId
确定能够处理它的"代理":
// in class Job
int getAgentId() { // return the "agent" who is responsible for @param job }
Run Code Online (Sandbox Code Playgroud)
A Task
被划分为多个子,Task
这样每个子都可以由一个单独的"代理"处理:
// in class Partition; `Integer` for "agent" id
Map<Integer, Task> partition(Task task) { }
Run Code Online (Sandbox Code Playgroud)
我的尝试: …
我工作在以下定理的证明Sn_le_Sm__n_le_m
中IndProp.v
的软件基础(第1卷:逻辑基础)。
Theorem Sn_le_Sm__n_le_m : ?n m,
S n ? S m ? n ? m.
Proof.
intros n m HS.
induction HS as [ | m' Hm' IHm'].
- (* le_n *) (* Failed Here *)
- (* le_S *) apply IHSm'.
Admitted.
Run Code Online (Sandbox Code Playgroud)
其中,的定义le (i.e., ?)
是:
Inductive le : nat ? nat ? Prop :=
| le_n n : le n n
| le_S n m (H : le n m) : …
Run Code Online (Sandbox Code Playgroud) 这是 Leslie Lamport 的《教学并发》一文中的一个简单并发程序。
考虑N
编号从 0 到N-1
每个进程i
执行的进程
x[i] := 1
y[i] := x[(i - 1) % N]
Run Code Online (Sandbox Code Playgroud)
并停止,其中每个x[i]
初始值都等于 0。(假设每个的读取和写入x[i]
都是原子的。)
该算法满足以下性质:每个进程停止后,y[i]
至少有一个进程等于1 i
。很容易验证:最后i
写入的进程y[i]
必须将其设置为1。
然后,兰波特评论说
但该进程并未设置
y[i]
为 1,因为它是最后一个写入的进程y
。该算法满足此属性,因为它保持归纳不变量。你知道那个不变量是什么吗?如果不是,那么你就没有完全理解为什么算法满足这个属性。
所以,
并发程序的归纳不变量是什么?
java ×5
java-8 ×3
java-stream ×3
concurrency ×2
lambda ×2
arrays ×1
collectors ×1
consensus ×1
coq ×1
coq-tactic ×1
correctness ×1
exception ×1
for-loop ×1
graphviz ×1
hashmap ×1
induction ×1
invariants ×1
layout ×1
locking ×1
paxos ×1
tla+ ×1
tlaps ×1