java并发以前发生过
假设你有两个线程和一个共享的对象数组列表,然后你进入其中一个线程,通过添加更多的对象来改变整个arraylistjava并发以前发生过,java,multithreading,Java,Multithreading,假设你有两个线程和一个共享的对象数组列表,然后你进入其中一个线程,通过添加更多的对象来改变整个arraylist static ArrayList<Object> o = static Object lock = new Object(); 然后每隔一段时间让线程2执行类似的操作 synchronized(lock){} o.get(7); 该列表最终将得到正确更新,但在线程1中更改其访问权限。这是不允许的吗?或者它是否能正常运行?未指定该行为。理
static ArrayList<Object> o =
static Object lock = new Object();
然后每隔一段时间让线程2执行类似的操作
synchronized(lock){}
o.get(7);
该列表最终将得到正确更新,但在线程1中更改其访问权限。这是不允许的吗?或者它是否能正常运行?未指定该行为。理论上,
addAll()
的实现方式可以使o.get(7)
抛出异常、挂起、返回错误值或执行任何其他操作
对于ArrayList
来说,挂起是一个不太可能的选择,但是其他结构(如HashMap
,LinkedList
,…)就不那么宽容了
所以基本上你不想依赖于“不会那么糟糕吧?”
有一个列表实现,它基本上实现了“在进行更改时读取旧内容”,它是。如果您只关心正确的读取,但并不总是需要最新的读取,并且如果写入远不如读取常见,那么这可能是一个很好的解决方案。没有指定行为。理论上,
addAll()
的实现方式可以使o.get(7)
抛出异常、挂起、返回错误值或执行任何其他操作
对于ArrayList
来说,挂起是一个不太可能的选择,但是其他结构(如HashMap
,LinkedList
,…)就不那么宽容了
所以基本上你不想依赖于“不会那么糟糕吧?”
有一个列表实现,它基本上实现了“在进行更改时读取旧内容”,它是。如果您只关心正确的读取,但并不总是需要最新的读取,如果写入远不如读取常见,那么这可能是一个很好的解决方案。您试图解决的问题是什么?您知道
o
没有正确同步,因此这是不安全的。找出它到底有多“不安全”有什么好处?将所有对象添加到arraylist的操作很长,因此将其视为volatile会更快。但是你的回答解释了如果它未指定,那么它可能应该被锁定。谢谢你的好意(如果写信给它比从中阅读要难得多的话),那么我也许能让你对一本书感兴趣。它是“最终一致的”,读取速度非常快(并且读取在写入时从不被阻止)。@SamAdams问题是线程1中的同步块不会阻止线程2在线程1执行addAll()
时尝试获取元素。当这种情况发生时,所有的赌注都输光了。你甚至可能最终陷入无法摆脱的比赛状态@萨马丹斯:不,甚至不要试图做出这样的假设。有些线程可能会决定根本不使用缓存,然后会进行操作重新排序,所有这些都是线程可以做的完全有效的事情。唯一的保证是围绕内存障碍的保证,如同步
和易失性
变量,但必须小心后者:私有易失性数组列表代码>不会对列表本身进行修改,只会分配到列表
字段。您试图解决的问题是什么?您知道o
没有正确同步,因此这是不安全的。找出它到底有多“不安全”有什么好处?将所有对象添加到arraylist的操作很长,因此将其视为volatile会更快。但是你的回答解释了如果它未指定,那么它可能应该被锁定。谢谢你的好意(如果写信给它比从中阅读要难得多的话),那么我也许能让你对一本书感兴趣。它是“最终一致的”,读取速度非常快(并且读取在写入时从不被阻止)。@SamAdams问题是线程1中的同步块不会阻止线程2在线程1执行addAll()
时尝试获取元素。当这种情况发生时,所有的赌注都输光了。你甚至可能最终陷入无法摆脱的比赛状态@萨马丹斯:不,甚至不要试图做出这样的假设。有些线程可能会决定根本不使用缓存,然后会进行操作重新排序,所有这些都是线程可以做的完全有效的事情。唯一的保证是围绕内存障碍的保证,如同步
和易失性
变量,但必须小心后者:私有易失性数组列表代码>不会对列表本身进行修改,只分配给列表
字段。
synchronized(lock){}
o.get(7);