根据文档,Java在并发包中提供了一个Lock对象 provides more extensive locking operations than can be obtained using synchronized methods and statements.
除了互斥之外的同步方法/块,强制执行先发生关系,这确保一个线程对变量的更改对另一个线程可见.
使用Lock对象时是否会出现这种关系?对于所有平台,观察是否保证像同步块一样?
假设我有两个运行方式:
线程A快速执行工作,比如说每秒100万次更新,所以我怀疑经常在锁/互斥锁/监视器上锁定和解锁是个坏主意.但是如果没有锁定并且无法建立从线程A到线程B的先发生关系,那么通过Java内存模型(JMM规范),线程B根本不能保证看到A对图像的任何更新.
所以我认为最小的解决方案是线程A和B在同一个共享锁上定期同步,但在synchronized块内部实际上不执行任何工作 - 这就是使模式非标准和可疑的原因.用半实半伪代码来说明:
class ComputationCanvas extends java.awt.Canvas {
private Object lock = new Object();
private int[] pixels = new int[1000000];
public ComputationCanvas() {
new Thread(this::runThreadA).start();
new Thread(this::runThreadB).start();
}
private void runThreadA() {
while (true) {
for (1000 steps) {
update pixels directly
without synchornization
}
synchronized(lock) {} // Blank
}
}
private void runThreadB() {
while (true) {
Thread.sleep(100);
synchronized(lock) {} // Blank
this.repaint();
}
}
@Override
public void paint(Graphics g) {
g.drawImage(pixels, 0, 0);
} …Run Code Online (Sandbox Code Playgroud) java multithreading synchronization java-memory-model happens-before
我对两个actor,父 P和子 C进行了以下顺序操作:
context watch c)context unwatch c)c ! PoisonPill)我想知道的是; 我保证P 不会收到C的Terminated活动吗?
这是一段代码示例
class HappensBefore extends App {
class C extends Actor { def receive = {} }
class P extends Actor {
val c = context actorOf Props[C]
context watch c
context unwatch c
c ! PoisonPill
def receive = { case …Run Code Online (Sandbox Code Playgroud) 关于JLS ch17 线程和锁,它说"如果一个动作发生在另一个之前,那么第一个动作在第二个之前可见并且在第二个之前被命令"; 我想知道:
(1)说"之前订购"的真正含义是什么?因为即使action_a发生在action_b之前,action_a也可以在action_b之后的某些实现中执行,对吧?
(2)如果action_a发生在action_b之前,是否意味着action_a绝不能看到action_b?或者action_a可能会看到或看不到action_b?
(3)如果action_a没有发生 - 在action_b之前,而action_b没有发生 - 在action_a之前,是否意味着action_a可能会看到或看不到action_b?
(4)之前没有任何循环发生,对吧?
任何答案将不胜感激:)
Executor接口的Javadoc说明如下:
内存一致性影响:在将
Runnable对象提交到Executor执行开始之前发生的线程中的操作(可能在另一个线程中)。
Java 语言规范的哪一部分保证了这一点?或者仅仅是因为实现使用了一些内部同步?(如果是这样的话,一个例子就很好了。)那么在实现自定义时Executor我应该注意这个要求吗?
Kotlin协程是否提供任何“事前保证”?
例如,mutableVar在这种情况下,对(可能)其他线程的写入和后续读取之间是否存在“先于后继”保证:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
Run Code Online (Sandbox Code Playgroud)
编辑:
也许其他示例可以更好地阐明这个问题,因为它更具Kotlin风格(可变性除外)。这段代码是线程安全的吗:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
Run Code Online (Sandbox Code Playgroud) 很确定它是这样的 - 但我想确定地知道 - 在 invokeLater() 或 invokeAndWait() 的情况下给出的关系是发生在之前吗?
这些方法在(分别为 SwingUtilities)AWT.EventQueue 中定义。我想当在 EventQueue 中输入一些东西时会涉及同步,因此作为同步的结果,发生了关系,最后给出了可见性。
但真的是这样吗?(我在哪里可以找到这些信息?)
例如在一些工作线程内
...
*<1> heavy computation modifying lots of DATA*
...
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
*<2> is visibility of modified DATA guaranteed?*
}
}
);
Run Code Online (Sandbox Code Playgroud)
例如在一些线程内
...
SwingUtilities.invokeAndWait(
new Runnable() {
@Override
public void run() {
...
*<1> change some DATA*
}
}
);
*<2> is visibility of modified DATA guaranteed?*
Run Code Online (Sandbox Code Playgroud) 阵列元素是否在工人之间正确发布?
假设我有一个大数组(任何原子数据类型,所以没有long或double),
future.get()).工人不会退货.它只是填充我的阵列.换句话说,它保证了前一个工作者的最后一次写入发生在第一次读取下一个工作者之前?
我是否应该(或者为了最佳实践或某事)让第一个工作人员返回数组,即使引用与我已经拥有的引用相同?
[编辑]一些背景:我使用byte数组或short数组,它们代表图像,每个使用多达500,000,000个元素.我对每个元素执行简单的算术运算.
我正在阅读《Java并发实践》,在“16.1.3 500字以内的Java内存模型”中,它说:
\n\n\n\n\nJava 内存模型是根据操作来指定的,包括对变量的读取和写入、监视器的锁定和解锁以及线程的启动和加入。JMM为程序中的所有操作定义了一个名为“happens-before”的部分排序。为了保证执行动作B的线程可以看到动作A的结果(无论A和B是否发生在不同的线程中),A和B之间必须存在happens-before关系。在没有happens-before排序的情况下在两个操作之间,JVM 可以随意对它们重新排序。
\n\n尽管动作只是部分有序的,但同步动作\xe2\x80\x94锁的获取和释放以及易失性变量\xe2\x80\x94的读写都是完全有序的。这使得根据 \xe2\x80\x9csubsequent\xe2\x80\x9d 锁定获取和易失性变量的读取来描述发生之前是有意义的。
\n
关于“部分排序”,我找到了这个和这个,但我不太明白“即使动作只是部分排序,同步动作\xe2\x80\x94锁获取和释放,以及易失性变量的读写\ xe2\x80\x94 是完全有序的。” 。“同步操作完全有序”是什么意思?
\n当今许多编程语言都具有happens-before关系和release+acquire同步操作。
其中一些编程语言:
\n\n我想知道是否release+acquire可以违反happens-before:
release+acquire和happens-beforeRelease/acquire建立happens-before不同线程之间的关系:换句话说,保证releasein之前的所有内容在afterThread 1中可见:Thread 2acquire
\\ Thread 1 / \n \\ -------- / \n \\ x = 1 / Everything \n \\ y …Run Code Online (Sandbox Code Playgroud) happens-before ×10
java ×8
concurrency ×3
memory-model ×2
actor ×1
akka ×1
c++ ×1
invokelater ×1
jvm ×1
jvm-hotspot ×1
kotlin ×1
locking ×1
scala ×1
swing ×1