本文的目的是介绍如果完全像compareAndSet那样实现weakCompareAndSet会失败吗?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于android–没
本文的目的是介绍如果完全像compareAndSet那样实现weakCompareAndSet会失败吗?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于android – 没有实现接口成员’IComparable.CompareTo(Object)’、android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat的实例源码、AtomicBoolean中的getAndSet和compareAndSet之间的区别、AtomicReference 的 compareAndSet 更新问题的知识。
本文目录一览:- 如果完全像compareAndSet那样实现weakCompareAndSet会失败吗?
- android – 没有实现接口成员’IComparable.CompareTo(Object)’
- android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat的实例源码
- AtomicBoolean中的getAndSet和compareAndSet之间的区别
- AtomicReference 的 compareAndSet 更新问题
如果完全像compareAndSet那样实现weakCompareAndSet会失败吗?
(请注意,此问题不是关于CAS的,而是关于 “可能偶然失败”的 Javadoc)。
AtomicInteger
该类中这两个方法之间Javadoc的唯一区别是, weakCompareAndSet 包含以下注释:
“可能会虚假失败” 。
现在,除非我的眼睛被某种咒语欺骗,否则这两种方法的确看起来完全一样:
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/* ... * May fail spuriously. */public final boolean weakCompareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
因此,我意识到“ May”并不意味着“ Must”,但是为什么我们不都开始将其添加到我们的代码库中:
public void doIt() { a();}/** * May fail spuriously */public void weakDoIt() { a();}
我真的与混淆 weakCompareAndSet() ,似乎做同样的 compareAndSet() 还认为“可能会意外失败”,而另一个不能。
显然,“弱”和“虚假失败”与“先发生”排序有关,但是我对这两种AtomicInteger(和AtomicLong等)方法仍然感到困惑:
因为显然它们调用的是完全相同的 不安全方法.compareAndSwapInt 方法。
我对AtomicInteger
Java 1.5中引入的内容感到特别困惑,因此在Java内存模型更改之后(因此,它显然不会 “在1.4中错误地失败”,
但其行为更改为 “在1.5中不会错误地失败” )。
答案1
小编典典实现和规范之间有区别…
尽管在特定的实现上,提供不同的实现可能没有多大意义,但是未来的实现可能在不同的硬件上可能想要。此方法是否在API中发挥作用还是有争议的。
同样,这些weak
方法没有 在 定义顺序 之前发生 。非weak
版本的行为类似于volatile
字段。
android – 没有实现接口成员’IComparable.CompareTo(Object)’
我有一个android的.aar文件.我试图在我的xamarin.android应用程序中使用它.我按照链接@L_301_1@中给出的步骤进行操作
但是当我尝试构建我的库时,我遇到了错误
“没有实现接口成员’IComparable.Compareto(Object)’”
我找到了一些解决方案,其中提到在Metadata.xml中我们需要添加一些属性.所以我在那里添加了以下行
path="/api/package[@name='com.logicjunction.ljindoorandroidsdk']/class[@name='FloorPlanBeaconsMapping']/implements[@name='java.lang.Comparable']"
NAME = “类型” > java.lang.Comparable的>
但仍然得到同样的错误.我怎么解决这个问题?
解决方法:
在没有接口实现的情况下构建库时获取错误IComparable.Compareto:
要解决此问题,需要在“Additions”文件夹中创建需要接口成员实现“IComparable.Compareto(Object)”的库类的部分类,如下所示:
命名空间应该与绑定库相同,在这种情况下,它是:“Hirondelle.Date4j”.
using java.lang;
namespace Hirondelle.Date4j
{
public partial class DateTime : Object, IComparable
{
int IComparable.Compareto(Object obj)
{
return Compareto((DateTime)obj);
}
}
}
然后应该成功构建库.
android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat的实例源码
@Override public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) { // Place an action bar item for searching. MenuItem item = menu.add("Search"); item.setIcon(android.R.drawable.ic_menu_search); MenuItemCompat.setShowAsAction(item,MenuItemCompat.SHOW_AS_ACTION_IF_ROOM | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); final View searchView = SearchViewCompat.newSearchView(getActivity()); if (searchView != null) { SearchViewCompat.setonQueryTextListener(searchView,new OnQueryTextListenerCompat() { @Override public boolean onQueryTextChange(String newText) { // Called when the action bar search text has changed. Since this // is a simple array adapter,we can just have it do the filtering. mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; mAdapter.getFilter().filter(mCurFilter); return true; } }); SearchViewCompat.setonCloseListener(searchView,new OnCloseListenerCompat() { @Override public boolean onClose() { if (!TextUtils.isEmpty(SearchViewCompat.getQuery(searchView))) { SearchViewCompat.setQuery(searchView,null,true); } return true; } }); MenuItemCompat.setActionView(item,searchView); } }
@Override public void onCreateOptionsMenu(Menu menu,searchView); } }
@Override public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) { // 客户列表菜单 inflater.inflate(R.menu.transnode_list,menu); // 获取“搜索按钮”菜单控件 MenuItem item = menu.findItem(R.id.action_search); final SearchView searchView = (SearchView) item.getActionView(); if (searchView != null) { SearchViewCompat.setonQueryTextListener(searchView,new OnQueryTextListenerCompat() { @Override public boolean onQueryTextChange(String newText) { return true; } // 当搜索结果提交时执行 @Override public boolean onQueryTextSubmit(String query) { if (!TextUtils.isEmpty(query)) { RefreshList(query); SearchViewCompat.setQuery(searchView,true); } return true; } }); SearchViewCompat.setonCloseListener(searchView,new OnCloseListenerCompat() { @Override public boolean onClose() { if (!TextUtils.isEmpty(SearchViewCompat .getQuery(searchView))) { SearchViewCompat.setQuery(searchView,true); } return true; } }); MenuItemCompat.setActionView(item,searchView); } }
@Override public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) { // 客户列表菜单 inflater.inflate(R.menu.customer_list,searchView); } }
@Override public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) { // Todo Auto-generated method stub MenuItem search = menu.findItem(R.id.action_search); final SearchView searchView = (SearchView) search.getActionView(); searchView.setQueryHint("网点名称,区域码..."); if (searchView != null) { SearchViewCompat.setonQueryTextListener(searchView,new OnQueryTextListenerCompat() { @Override public boolean onQueryTextChange(String newText) { return true; } // 当搜索结果提交时执行 @Override public boolean onQueryTextSubmit(String query) { if (!TextUtils.isEmpty(query)) { loadNodesLatlng(query); SearchViewCompat.setQuery(searchView,true); } return true; } }); MenuItemCompat.setActionView(search,searchView); } super.onCreateOptionsMenu(menu,inflater); }
@Override public void onCreateOptionsMenu(Menu menu,MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); final View searchView = SearchViewCompat.newSearchView(getActivity()); if (searchView != null) { SearchViewCompat.setonQueryTextListener(searchView,new OnQueryTextListenerCompat() { @Override public boolean onQueryTextChange(String newText) { // Called when the action bar search text has changed. Update // the search filter,and restart the loader to do a new query // with this filter. String newFilter = !TextUtils.isEmpty(newText) ? newText : null; // Don't do anything if the filter hasn't actually changed. // Prevents restarting the loader when restoring state. if (mCurFilter == null && newFilter == null) { return true; } if (mCurFilter != null && mCurFilter.equals(newFilter)) { return true; } mCurFilter = newFilter; getLoaderManager().restartLoader(0,CursorLoaderListFragment.this); return true; } }); SearchViewCompat.setonCloseListener(searchView,searchView); } }
@Override public void onCreateOptionsMenu(Menu menu,searchView); } }
AtomicBoolean中的getAndSet和compareAndSet之间的区别
线程标题应该是不言自明的…我对以下来自AtomicBoolean
类的方法的规范有些困惑:
java.util.concurrent.atomic.AtomicBoolean#compareAndSet
java.util.concurrent.atomic.AtomicBoolean#getAndSet
我的追求是当用作if
条件中的布尔子句时,两者将导致相同的行为:
public class Test {
private AtomicBoolean flag = AtomicBoolean(false);
public void processSomeAction() {
if (flag.getAndSet(false)) { // Shouldn't this be similar to flag.compareAndSet(false)
// process some action
}
}
//...
private void internalMutatorMethod() {
// do some staff then update the atomic flag
flas.set(true);
}
}
假设我要检索当前标志值并自动更新它,这两种方法难道不会产生相同的行为吗?
如果我遗漏了内部差异,那么我将不胜感激任何有关如何以及何时使用它们的解释。
AtomicReference 的 compareAndSet 更新问题
最近在学习 AtomicInteger 可能导致的 ABA 问题以及解决办法。
当学习到原子引用时,遇到了一个问题。不多说,开始:
一、问题代码
DEMO-1:
public class ABADemo {
static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
public static void main(String[] args) {
new Thread(() -> {
System.out.println(atomicReference.compareAndSet(100, 127));
System.out.println(atomicReference.compareAndSet(127, 100));
System.out.println(atomicReference.get());
},"T1").start();
}
}
打印结果:
可见,两次比较并更新均成功了。
DEMO-2:
public class ABADemo {
static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
public static void main(String[] args) {
new Thread(() -> {
System.out.println(atomicReference.compareAndSet(100, 128));
System.out.println(atomicReference.compareAndSet(128, 100));
System.out.println(atomicReference.get());
},"T1").start();
}
}
打印结果:
这次出现了问题:第一次更新成功,第二次更新失败。
两段代码唯一不一样的地方就是第一次更新的值,前者为 127,后者为 128。
二、原因
1. AtomicReference.compareAndSet 通过 “==” 比较,即比较的内容是否为同一地址。
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
2. 对于 java 的字面量,Java 会对其自动装箱为其包装类对象。
int 通过 Integer.value () 方法包装成 Integer 对象,
short 通过 Short.value () 方法包装成 Short 对象,
long 通过 Long.value () 方法包装成 Long 对象。
以 int 类型为例:Integer.valueOf 源码:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
由源码可知,int 再包装为 Integer 时,如果 int 值在 - 128 到 127 之间,会直接从缓存中获取;否则会直接 new 一个新的 Integer 对象。(缓存最大值一般就是 127,有可能会通过虚拟机配置改为其他值)
所以在我们从 100 更新为 128 时,对于 128 是 new 了一个新对象;128 再更新成 100 时,对于 128 会再 new 一个新对象。相当于两次比较并替换操作里的 128,是两个不同的对象,用 == 比较,自然是返回 false。
所以就出现了我上面的情况。
三、short 和 long
1. short
/**
* Returns a {@code Short} instance representing the specified
* {@code short} value.
* If a new {@code Short} instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Short(short)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param s a short value.
* @return a {@code Short} instance representing {@code s}.
* @since 1.5
*/
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
2. long
/**
* Returns a {@code Long} instance representing the specified
* {@code long} value.
* If a new {@code Long} instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Long(long)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* Note that unlike the {@linkplain Integer#valueOf(int)
* corresponding method} in the {@code Integer} class, this method
* is <em>not</em> required to cache values within a particular
* range.
*
* @param l a long value.
* @return a {@code Long} instance representing {@code l}.
* @since 1.5
*/
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
所以对于 short 和 long 类型的 ABA 比较并替换操作,也会出现大于等于 128 时,第二次无法更新成功的问题。
今天关于如果完全像compareAndSet那样实现weakCompareAndSet会失败吗?的介绍到此结束,谢谢您的阅读,有关android – 没有实现接口成员’IComparable.CompareTo(Object)’、android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat的实例源码、AtomicBoolean中的getAndSet和compareAndSet之间的区别、AtomicReference 的 compareAndSet 更新问题等更多相关知识的信息可以在本站进行查询。
本文标签: