Pac*_*ier 4 java synchronization
我有一个Thread-X,它每秒读取一个非易失性变量,这样做没有任何同步手段.
现在我想知道是否有某种方法可以修改Thread-Y上的非易失性变量,以便Thread-Y的写入(最终)在Thread-X上可见?
public class Test {
private static boolean double = 1; // this variable is
// strictly not volatile
public static void main(String args[]) {
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
while (true) {
System.out.println(variable);
try {
java.lang.Thread.currentThread().sleep(1000);
} catch (java.lang.InterruptedException e) {
}
}
}
}).start(); // line 17
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
// the task is to change variable to "2" such the write
// is (eventually) registered by the other threads
// allowed to use any synchronization/locking techniques
// required, but line 1 to line 17 must not be changed
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以修改非易失性变量,以便在没有任何同步技术(原始读取)的情况下读取它的另一个线程能够最终"看到"更新?
背景:
我需要从大量线程中读取一个变量,无数次.
根据我的理解(纠正我,如果我错了),在大多数cpus(例如x86)读取volatile变量是"几乎完全免费"但不是"完全免费".
既然我有无数个线程的无限次读取,我希望变量是非易失性的.然而,一旦在蓝色的月亮中,变量需要更新.在我的用例中,更新该变量需要花费多少并不重要,但该更新最终必须由读取器线程读取.
解决方案:
基于Tomasz的评论,我已经构建了这个解决方案,我想知道解决方案-1是否有缺陷或者它是否可靠?
public class Solution1 {
private static double variable = 1; // this variable is
// strictly not volatile
public static void main(String args[]) {
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
while (true) {
System.out.println(variable);
try {
java.lang.Thread.currentThread().sleep(1000);
} catch (java.lang.InterruptedException e) {
}
}
}
}).start(); // line 17
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
variable = 2;
// writer-thread now terminates,
// is it guaranteed that when it
// "terminates successfully", variable
// is updated on the reader-thread ?
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
基于Joonas的评论,我已经构建了这个解决方案,我想知道解决方案-2是否有缺陷或者它是否可靠?
public class Solution2 {
private static double variable = 1; // this variable is
// strictly not volatile
private static volatile boolean lock = false;
public static void main(String args[]) {
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
while (true) {
System.out.println(variable);
try {
java.lang.Thread.currentThread().sleep(1000);
} catch (java.lang.InterruptedException e) {
}
}
}
}).start(); // line 17
new java.lang.Thread(new java.lang.Runnable() {
@Override
public void run() {
variable = 2;
lock = false; // does this line guarantee
// that other threads will now
// see the update to variable (piggypacking)?
// now let's assume this thread doesn't terminate
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以修改非易失性变量,以便在没有任何同步技术(原始读取)的情况下读取它的另一个线程能够最终"看到"更新?
号有些同步技术必须使用,因为否则(JIT)编译器被允许优化线System.out.println(false);(如果false是首先由该线程看到的值).也就是说,它可以优化读取变量.
我不知道它实际上有多大可能做到这一点,但根据Java内存模型可以,所以你的选择是:
volatile.这可能是您最简单,最轻的选择.AtomicBoolean.在这里和这里讨论它与易变性.synchronized块.在这种情况下矫枉过正.java.util.concurrent.locks.Lock.比以往更多的功能synchronized.Thread.join().在这种情况下没用(读取线程会等待编写器终止).只需使用volatile并让JVM担心有效地实现它.它不贵.
| 归档时间: |
|
| 查看次数: |
1626 次 |
| 最近记录: |