Class Future
{
private volatile boolean ready;
private Object data;
public Object get()
{
if(!ready) return null;
return data;
}
public synchronized void setOnce(Object o)
{
if(ready) throw...;
data = o;
ready = true;
}
}
它说,“如果一个线程读取数据,在从写到读的过程中会有一个确保数据可见性的先兆”
我从我的学习中知道:
我的困惑是
>
get()不同步,这意味着同步锁无法保护setOnce(),因为线程1调用get(),而get()无需获取锁即可访问变量就绪数据。所以线程不能保证看到数据的最新值。我的意思是锁只保证同步块之间的可见性。即使一个线程正在运行synchronized block setOnce(),另一个线程仍然可以进入get(),在不阻塞的情况下访问ready和data,并且可以看到这些变量的旧值。
在get()中,如果ready=true,则数据必须是o?我的意思是这个线程保证可以看到数据的可见性?我认为数据不是易变的,也不是同步的。该线程是否可以在缓存中看到旧值?
谢谢
易失性确保每次读/写都在内存中,而不仅仅是在缓存或寄存器中;
不。它只是确保其他线程可以看到它。在现代硬件上,这不需要访问内存。(这是一件好事,主内存很慢。)
volatile确保了重新排序:也就是说,在setOnce()方法中,data=o只能在if(ready)throw。。。,在准备好之前=真;这保证了如果in get()ready=true,数据必须是o。
没错。
当线程1在setOnce()中时,是否有可能达到after data=o;准备好之前=真;同时,线程2运行get(),read ready为false,并返回null。thead 1继续就绪=真。在这个场景中,线程2没有看到新的“数据”,即使数据在线程1中被分配了新的值。
是的,但如果这是一个问题,那么你不应该使用这样的代码。据推测,这段代码的API应该是,如果在setOnce
返回后调用get
,就可以确保看到结果。显然,您不能保证get
会在我们完成制作之前看到结果。
get()不同步,这意味着同步锁无法保护setOnce(),因为线程1调用get(),而get()无需获取锁即可访问变量就绪数据。所以线程不能保证看到数据的最新值。我的意思是锁只保证同步块之间的可见性。即使一个线程正在运行synchronized block setOnce(),另一个线程仍然可以进入get(),在不阻塞的情况下访问ready和data,并且可以看到这些变量的旧值。
不。如果这是真的,同步几乎不可能使用。例如,常见的模式是创建一个对象,然后获取集合上的锁,并将该对象添加到集合中。如果获取集合上的锁不能保证创建对象所涉及的写操作是可见的,那么这就行不通了。
在get()中,如果ready=true,则数据必须是o?我的意思是这个线程保证可以看到数据的可见性?我认为数据不是易变的,也不是同步的。该线程是否可以在缓存中看到旧值?
Java的volatile
操作的定义是,一个看到一个线程的更改的线程保证看到所有其他内存的更改,即在执行线程看到的更改之前执行该更改的线程。这在其他语言(如C或C)中是不正确的。这可能会使Java的挥发物在某些平台上更加昂贵,但幸运的是,在典型的平台上不是这样。
另外,请不要谈论“在缓存中”。这与缓存无关。这是一个常见的误解。它与可见性有关,而不是缓存。大多数缓存都提供对缓存的完全可见性(将“MESI协议”打入您最喜欢的搜索引擎以了解更多信息),并且不需要任何特殊的东西来确保可见性。
我有一段代码如下: 谢谢
我正在尝试制作一个程序,提示用户输入数字,直到输入一个非数值。此时,它结束并打印:计数、总和、平均值、最小值和最大值。我得到一个“int不能被取消引用”的错误。我不知道该怎么办。
我的Jenkins管道中的一个阶段应根据其步骤中脚本的退出代码设置为不稳定:2应将阶段状态设置为不稳定性,而1应将阶段结果设置为失败。 如何做到这一点?我检查了“catchError”,但它似乎没有区分失败状态,只提供了一种捕获非0退出(1,2...)的方法。
我不知道如何为这个程序编写JUnit测试。请帮忙。问题是 假设用户的个人识别码是“1234”,编写一个程序,向用户索要个人识别码不超过三次,并执行以下操作:如果用户输入正确的号码,打印一条消息说“您的个人识别码是正确的”,并结束程序... 如果用户输入了错误的号码,请打印一条消息,说明“您的PIN不正确”,如果您请求PIN的次数少于三次,请再次请求。如果用户三次输入错误的号码,请打印一条消息,说明
我目前正在开发一个程序,在我的子类中,我需要一个无参数构造函数,用空字符串初始化对象。 我尝试过使用super,我有setter和getter方法,但我一直得到“field Person.name不可见”。我得到这个地址和电话号码以及。 如何使其可见,并且我可以在不提供构造函数参数的情况下初始化对象?如果我做错了什么并需要修复某些内容,请告诉我(:
本文向大家介绍RabbitMQ 怎么保证消息的稳定性?相关面试题,主要包含被问及RabbitMQ 怎么保证消息的稳定性?时的应答技巧和注意事项,需要的朋友参考一下 提供了事务的功能。 通过将 channel 设置为 confirm(确认)模式。