java静态数组变量需要锁定吗?
假设我有一个静态变量,它是一个大小为5的数组。 假设我有两个线程,T1和T2,它们都试图改变数组索引0处的元素。然后使用索引0处的元素。 在这种情况下,我应该锁定数组,直到T1使用完元素,对吗
另一个问题是假设T1和T2已经在运行,T1首先访问索引0处的元素,然后锁定它。但就在T2试图访问索引0处的元素之后,T1还没有解锁索引0。那么在这种情况下,为了让T2访问索引0处的元素,T2应该做什么?T2应该在T1解锁数组的索引0后使用回调函数吗
你可以在下面搜索框中键入要查询的问题!
假设我有一个静态变量,它是一个大小为5的数组。 假设我有两个线程,T1和T2,它们都试图改变数组索引0处的元素。然后使用索引0处的元素。 在这种情况下,我应该锁定数组,直到T1使用完元素,对吗
另一个问题是假设T1和T2已经在运行,T1首先访问索引0处的元素,然后锁定它。但就在T2试图访问索引0处的元素之后,T1还没有解锁索引0。那么在这种情况下,为了让T2访问索引0处的元素,T2应该做什么?T2应该在T1解锁数组的索引0后使用回调函数吗
# 1 楼答案
你考虑过使用原子引用阵列吗http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/AtomicReferenceArray.html它提供了一个#getAndSet方法,它提供了一种线程安全的原子方法来更新索引
# 2 楼答案
不锁定变量;你锁定了一个互斥锁,它可以保护 特定范围的代码。规则很简单:如果有线程 修改一个对象,并且有多个线程访问它(例如 任何原因),所有访问都必须完全同步。照常 解决方案是定义一个互斥来保护变量request 一把锁在上面,一旦进入完毕,就释放锁。 当一个线程请求锁时,它将被挂起,直到该锁被释放 已经获释
在C++中,通常使用RAII来确保锁是 释放,无论块如何退出。在爪哇, 同步块将在开始时获取锁 (等待它可用),并在 程序离开了块(无论出于什么原因)# 3 楼答案
当有多个线程访问某个对象时,可以使用
synchronize
(锁)第二个线程将阻塞,直到第一个线程释放锁(退出同步块)
如果不想让线程阻塞,可以使用java.util.concurrent.locks和非阻塞检查进行更细粒度的控制
# 4 楼答案
java中的同步(从技术上讲)不是拒绝其他线程访问某个对象,而是确保在使用同步锁的线程之间(一次)唯一地使用该对象。因此,T2可以在T1拥有同步锁的情况下访问对象,但在T1释放同步锁之前,T2将无法获得同步锁
# 5 楼答案
1)基本上是的。您不必锁定数组,您可以在更高的粒度级别上锁定(例如,如果它是一个私有变量,则锁定封闭类)。重要的是,如果不持有相同的锁,代码的任何部分都不会试图修改或读取数组。如果违反此条件,可能会导致未定义的行为(包括但不限于看到旧值、看到从未存在的垃圾值、抛出异常和进入无限循环)
2)这在一定程度上取决于您使用的同步方案和所需的语义。使用标准的
synchronized
关键字,T2
将无限期阻塞,直到T1
释放监视器,此时T2
将获取监视器并继续同步块内的逻辑如果希望在争用锁时对行为进行更细粒度的控制,可以使用显式Lock对象。这些提供了
tryLock
方法(都有一个超时,并立即返回),根据是否可以获得锁返回true
或false
。因此,如果没有立即获得锁,您可以测试返回值并采取任何您喜欢的操作(例如注册回调函数、递增计数器以及在重试之前向用户提供反馈等)然而,这种定制反应很少是必要的,并且显著地增加了锁定代码的复杂性,更不用说,如果您忘记始终在
finally
块中释放锁,并且仅在成功获取锁时,错误的可能性很大,等等。作为一般规则,只需使用synchronized
,除非/直到您能够证明它为应用程序所需的吞吐量提供了一个显著的瓶颈# 6 楼答案
是的,为了避免比赛条件,这是个好主意
查看数组,然后读取值。现在你知道没有其他人可以修改它。当使用诸如
monitors
之类的锁时,系统会自动保留队列。因此,如果T2
试图访问被T1
锁定的对象,它将阻塞(挂起),直到T1
释放锁为止示例代码:
从技术上讲,您还可以在阵列本身上进行同步