使用任何java.util.concurrent类时,是否仍需要在实例上同步访问以避免差异线程之间的可见性问题?
当使用java.util.concurrent的实例时,是否有可能一个线程修改实例(即,将一个元素放在一个并发的hashmap中),后续的线程将不会看到修改?
我的问题源于这样一个事实:如果对值的访问不同步,Java内存模型允许线程缓存值而不是直接从内存中获取它们.
java concurrency multithreading java.util.concurrent java-memory-model
当我想知道Java 7发行版中是否有任何更改时,我正在重新阅读JSR-133规范.也就是说,如果133已经过时或仍然有效.
我没有在谷歌上找到关于Java 7内存模型变化的任何内容,但我在这里问以防万一有人知道.
我被告知使用volatile变量比使用synchronized块(读或写)时使用synchronized块要高效得多.
直到Java 1.4我才能看到原因(因为那时线程不必刷新并刷新所有可访问的内存).
但是从Java 1.5开始,我在使用volatile变量和synchronized块之间看到的唯一区别就是锁获取机制.
获得锁真的那么贵吗?如果是这样,为什么呢?
这是作者说的
3)字符串池是在Heap的PermGen区域中创建的,垃圾收集可以在perm空间中进行,但依赖于JVM到JVM.顺便提一下,从JDK 1.7更新,String池被移动到创建对象的堆区域.
它有什么具体的原因吗?我无法在网上找到任何内容.有什么影响?
最近我能够使用sun.misc.Unsafe类获取对象的地址.
现在我试图以编程方式找到我的对象所在的实际生成.为此,我想知道每一代的起点和终点.如果Java(Oracle JVM)提供了解决此问题的任何工具?我不相信,因为即使不同的GC也需要不同的内存结构(例如G1),这使得任务更加有趣:)
我想知道的只是代表内存中几代边界的几个数字,如下所示:
young gen: start point - 8501702198
end point - 9601256348
Run Code Online (Sandbox Code Playgroud)
愿意听到关于黑魔法的最疯狂的想法,它可以确定不同代区域在记忆中的位置.
我正在努力加深我对Java内存模型和JVM的了解.
基本概念很简单,但我无法理解JVM在哪里保存有关基元,对象和引用的类型的信息.
例如1.我们有变量int i = 0.这个值存储在线程的堆栈中.这只是一个4字节,在RAM或/和CPU缓存中包含值0x0000.但它不包含任何有关其类型的信息.想象一下,您可以直接访问内存中的这些字节.你不能确定它是一个整数.据我所知,你不能对它的类型说什么.这只是4个字节的信息.
因此,JVM必须在其他地方保留关于其类型的一些信息,但JVM在何处以及如何保留它?
一个obj = new B();
在这种情况下,我们有这样的事情:
| 堆栈| | HEAP | | PermGen的|
"引用"---->"对象""A","B".
引用位于堆栈中,类型为"A",但引用仅包含存储"对象"的信息.它有8字节(如果JVM使用少于32GB,可以压缩到4byte).它没有关于这8个字节中的类型的任何信息.
"对象"位于堆中,类型为"B".我不知道它是否有关于其类型的任何信息......
我希望有人能说清楚..
我的问题已提交至该帖子:https : //shipilev.net/blog/2014/safe-public-construction/
public class UnsafeDCLFactory {
private Singleton instance;
public Singleton get() {
if (instance == null) { // read 1, check 1
synchronized (this) {
if (instance == null) { // read 2, check 2
instance = new Singleton(); // store
}
}
}
return instance; // read 3
}
}
Run Code Online (Sandbox Code Playgroud)
并且,它写为:
请注意,我们在这段代码中对实例进行了多次读取,并且至少“ read 1”和“ read 3”是没有任何同步的读取?—也就是说,这些读取是正常的。Java内存模型的目的之一是允许对普通读取进行重新排序,否则性能成本将高得惊人。在规范方面,如一致性规则中之前所述,读取操作可以通过竞争观察无序写入。这是针对每个读取动作决定的,而不管其他什么动作已经读取同一位置。在我们的示例中,这意味着即使“ read 1”可以读取非null实例,但代码随后继续返回它,然后又读取了一个racy,并且可以读取null实例,该实例将被返回!
我不明白。我同意编译器显然可以重新排序内存操作。但是,这样做时,编译器必须从单线程的角度来看保留原始程序的行为。
在上面的示例中,read 1读取的结果为非null。在read 3读空。这意味着它read 3已由编译器重新排序,instance并优先读取到read 1(我们可以跳过CPU重新排序,因为该文章提出了Java内存模型)。
但是,在我看来,由于商店经营 …
我目前正在攻读并发编程考试并且不明白为什么这个程序的输出是43.为什么x = y + 1之前执行t.start()?我还应该解释在我使用的规则之前发生了什么.
如果我理解程序顺序规则(一个线程中的每个动作发生 - 在该程序顺序后面的那个线程中的每个动作之前)t.start()都必须在执行之前执行,x = y + 1以便线程t复制变量x1.
public class HappensBefore {
static int x = 0;
static int y = 42;
public static void main(String[] args) {
x = 1;
Thread t = new Thread() {
public void run() {
y = x;
System.out.println(y);
};
};
t.start();
x = y + 1;
}
Run Code Online (Sandbox Code Playgroud) java concurrency multithreading java-memory-model happens-before
我编写了这个简单的多线程程序,将1到100,000之间的数字相加。运行此命令时,最终结果得到的值不同(值小于预期的5000050000)。当我仅使用一个线程执行程序时,它给出了正确的结果。该程序还适用于较小的值,例如100。可能出了什么问题?提前致谢。
class Calculation {
private long total=0;
public void calcSum(long start, long end) {
long i = start;
for( ;i<=end; i++) {
total += i;
}
}
public long getTotal() {
return total;
}
}
class CalculatorThread extends Thread{
private long start;
private long end;
private Calculation calc;
public CalculatorThread(long start, long end, Calculation calc) {
this.start = start;
this.end = end;
this.calc = calc;
}
@Override
public void run() {
calc.calcSum(start, end);
}
}
public class ParallelTest {
public …Run Code Online (Sandbox Code Playgroud) java concurrency multithreading java-memory-model java-threads
看起来Java内存模型没有定义本地缓存的“刷新”和“刷新”,相反,人们只是为了简单起见才这样称呼它,但实际上“ happens-before”关系意味着以某种方式刷新和刷新(如果您可以对此进行解释,但不能直接成为问题的一部分)。
令我感到困惑的是,JLS中有关Java内存模型的部分并未以易于理解的方式编写。
因此,能否请您告诉我我在以下代码中所做的假设是否正确以及是否可以保证正常运行?
它部分基于Wikipedia文章中有关双重检查锁定的代码,但是作者在其中使用了包装器类(FinalWrapper),但这对我来说并不完全清楚。也许支持null价值观?
public class Memoized<T> {
private T value;
private volatile boolean _volatile;
private final Supplier<T> supplier;
public Memoized(Supplier<T> supplier) {
this.supplier = supplier;
}
public T get() {
/* Apparently have to use local variable here, otherwise return might use older value
* see https://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html
*/
T tempValue = value;
if (tempValue == null) {
// Refresh
if (_volatile);
tempValue = value;
if (tempValue == null) …Run Code Online (Sandbox Code Playgroud)