众所周知,如果我们有一些对象引用并且此引用具有final字段,则将确保-我们将看到final字段中的所有可访问字段(至少在构造函数完成时)
class Foo{
private final Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
正如我在这种情况下所理解的那样,我们保证该bar()
方法总是输出,object
因为:
1.我列出了class Foo
和map的完整代码是最终的;
2.如果某个线程将看到的引用,Foo
而该引用!= null,则我们保证从最终map
引用值可达到将是实际的。
我也认为
class Foo {
private final Map map;
private Map nonFinalMap;
Foo() {
nonFinalMap = new HashMap();
nonFinalMap.put(2, "ololo");
map = new HashMap();
map.put(1, "object");
}
public void bar() {
System.out.println(map.get(1));
}
public void bar2() {
System.out.println(nonFinalMap.get(2));
}
}
在这里,我们对bar()
方法有相同的保证,但是尽管在赋值之前发生
赋值,但还是bar2
可以抛出。NullPointerException``nonFinalMap``map
我想知道volatile:
class Foo{
private volatile Map map;
Foo(){
map = new HashMap();
map.put(1,"object");
}
public void bar(){
System.out.println(map.get(1));
}
}
据我了解,bar()
方法不能抛出NullPoinerException
但可以打印null
;(我完全不确定这方面)
class Foo {
private volatile Map map;
private Map nonVolatileMap;
Foo() {
nonVolatileMap= new HashMap();
nonVolatileMap.put(2, "ololo");
map = new HashMap();
map.put(1, "object");
}
public void bar() {
System.out.println(map.get(1));
}
public void bar2() {
System.out.println(nonFinalMap.get(2));
}
}
我认为,我们在这里有大约相同的注册就bar()
方法也bar2()
不能扔NullPointerException
,因为nonVolatileMap
转让的书面较高的挥发性映射分配,但它可以输出空
*在Elliott Frisch评论后 *添加
通过竞赛示例发布:
public class Main {
private static Foo foo;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
foo = new Foo();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (foo == null) ; // empty loop
foo.bar();
}
}).start();
}
}
请证明或更正我对代码段的注释。
在当前的Javahtml" target="_blank">html" target="_blank">内存模型领域中,volatile
不等于final
。换句话说,您不能将替换final
为volatile
,并认为安全构造保证是相同的。值得注意的是,这在理论上可能会发生:
public class M {
volatile int x;
M(int v) { this.x = v; }
int x() { return x; }
}
// thread 1
m = new M(42);
// thread 2
M lm;
while ((lm = m) == null); // wait for it
print(lm.x()); // allowed to print "0"
因此,volatile
在构造函数中编写字段并不安全。
直觉:m
上面的例子中有一场竞赛。创造 场地 并不能消除种族M.x
volatile
,只有制造m
自己volatile
会有所帮助。换句话说,volatile
该示例中的修饰符在 错误的位置
可用。在安全发布中,您必须具有“写入->易失性写入->易失性读取,可观察到易失性写入->读取(现在先观察易失性写入之前的写入)”,而必须具有“易失性写入->写入->读取-
易失性读取(不遵循易失性写入)”。
琐事1:
此属性表示我们可以volatile
在构造函数中更加积极地进行优化。这证实了this
可以放松未观察到的易失性存储的直觉(实际上,直到具有非转义完成的构造函数才观察到)。
琐事2:
这也意味着您不能安全地初始化volatile
变量。在上面的示例中替换M
为AtomicInteger
,您将具有独特的现实生活行为!调用new AtomicInteger(42)
一个线程,不安全地发布该实例,然后get()
在另一个线程中执行-
您是否保证遵守42
?如前所述,JMM说“不”。Java内存模型的最新修订版努力确保所有初始化的安全构造,以捕获这种情况。许多重要的非x86端口已经加强了它的安全性。
Trivia 3: Doug Lea:“ final
vs
volatile
问题导致在java.util.concurrent中进行了一些曲折的构造,以允许在自然不存在的情况下将0用作基本/默认值。该规则很糟糕,应该更改。”
也就是说,可以使示例更加狡猾:
public class C {
int v;
C(int v) { this.x = v; }
int x() { return x; }
}
public class M {
volatile C c;
M(int v) { this.c = new C(v); }
int x() {
while (c == null); // wait!
return c.x();
}
}
// thread 1
m = new M(42);
// thread 2
M lm;
while ((lm = m) == null); // wait for it
print(lm.x()); // always prints "42"
如果 在 volatile读取观察到volatile写入构造函数中写入的值 之后
存在一个传递性直读volatile
字段,则通常的安全发布规则开始生效。 __
我正在学习著名的《关于Java》一书。这本书说:“如果一个线程写入一个变量,而其他线程只读取它,那么你可以让该变量保持易失性。”我不明白为什么不需要“易失性”来确保将线程刷新变量写回内存?如果没有易失性,其他线程是否会因为本地缓存而读取脏数据?
问题内容: JVM是否保证不缓存非可变变量? 程序员是否可以依赖JVM始终为每个线程本地缓存非易失性变量。 或JVM可能会或可能不会这样做,因此程序员不应为此而依赖JVM。 预先感谢您的回答。 问题答案: 否。JVM不能保证“缓存”非易失性字段。JVM保证的实现是 可变字段应如何表现 。字段的缓存是非标准的(未指定),并且因JVM的实现而异。因此,您不应该真正依赖它(即使通过某种方式发现某些数据正
问题内容: 我有一个缓存类,其中包含一个存储缓存项。 我很好奇更改为会带来什么后果? 我会提高性能吗?此缓存是只读缓存。 最佳选择是什么?只是HashMap?缓存将按一定间隔进行填充。 问题答案: 首先,您似乎不了解关键字的作用。它确保如果声明的变量保留的 引用值发生更改,则其他线程将看到它,而不是拥有缓存的副本。它与访问线程安全无关。 鉴于此,并且您说的是只读事实,您当然不需要使用任何提供线程安
Perl 语言编程,第四版 称为大骆驼书,真正的 Perl 圣经。 Perl 语言入门,第六版 称为小骆驼书,Perl 标准教程。 Perl Cookbook,第二版 一本如何利用 Perl 干活的问题导向书籍。 Object Oriented Perl 关于 Perl 5 面向对象编程的最佳解释。 Perl 最佳实践 展示如何写优良、可维护的 Perl 代码。 The Perl Review 在
我目前添加了一个CSRF令牌保护机制到我的php应用程序。正如我所读到的,唯一的要求是一个独特的每个用户令牌,我在php7中使用random_bytes生成。 我担心的是,如果攻击者使用用户的浏览器发送http请求,浏览器不会发送令牌的会话变量吗?(因为用户具有与令牌关联的sessionid)。 我将令牌存储在会话变量的一个隐藏值内。 例如:我的令牌存储在会话变量中,然后攻击者将我发送到具有csr
问题内容: 这个问题与尚未使用的intl-tel-input和vuejs2一起使用相似。 因此,长话短说,我正在动态设置一个新的引导程序选项卡(标题和URL),然后尝试使用来(重新)绑定某些功能。 在我的Vue方法中添加以下行https://github.com/thecodeassassin/bootstrap-remote-data/blob/master/js/bootstrap-remot