静态数组变量需要锁定吗?

时间:2011-03-16 17:09:06

标签: java c++ concurrency locking mutex

所以我想说我有一个静态变量,它是一个大小为5的数组。 让我们说我有两个线程,T1和T2,它们都试图改变该数组的索引0处的元素。然后使用索引0处的元素。 在这种情况下,我应该使用右边的元素锁定数组,直到T1完成?

另一个问题是让我们说T1和T2已经在运行,T1访问元素首先在索引0,然后锁定它。但是在T2尝试访问索引0处的元素之后,T1还没有解锁索引0。那么在这种情况下,为了让T2访问索引0处的元素,T2应该做什么? T1解锁数组索引0后T2应该使用回调函数吗?

7 个答案:

答案 0 :(得分:1)

  

我应该锁定数组,直到T1使用右边的元素完成?

是的,以避免竞争条件,这将是一个好主意。

  

T2应该做什么

查看数组,然后读取值。此时你知道没有其他人可以修改它。使用诸如monitors之类的锁时,系统会自动保留队列。因此,如果T2尝试访问由T1锁定的对象,它将阻止(挂起)直到T1释放锁定。

示例代码:

private Obect[] array;
private static final Object lockObject = new Object();

public void modifyObject() {
    synchronized(lockObject) {
       // read or modify the objects
    }
}

从技术上讲,您也可以在阵列上进行同步。

答案 1 :(得分:1)

当你要让多个线程访问某些内容时,你synchronize(锁定)。

第二个线程将阻塞,直到第一个线程释放锁定(退出同步块)

如果您不希望线程阻塞,可以使用java.util.concurrent.locks并使用非阻塞检查来进行更细粒度的控制。

答案 2 :(得分:1)

1)基本上,是的。您无需锁定数组,您可以锁定更高级别的粒度(例如,如果它是私有变量,则为封闭类)。重要的是,代码的任何部分都不会尝试修改或从读取数组而不保持相同的锁。如果违反此条件,可能会导致未定义的行为(包括但不限于查看旧值,查看从未存在的垃圾值,抛出异常以及进入无限循环)。

2)这部分取决于您正在使用的同步方案以及您想要的语义。使用标准synchronized关键字,T2将无限期阻止,直到T1释放监视器,此时T2将获取监视器并继续同步内部的逻辑块。

如果您希望在争用锁时对行为进行更细粒度的控制,则可以使用显式Lock对象。这些方法提供tryLock方法(两者都有超时,并立即返回),根据是否可以获得锁定,返回truefalse。因此,如果没有立即获得锁定,您可以测试返回值并采取您喜欢的任何操作(例如注册回调函数,递增计数器并在再次尝试之前向用户提供反馈等)。

然而,这种自定义反应很少是必要的,并且显着增加了锁定代码的复杂性,更不用说如果您忘记始终在finally块中释放锁定时出现错误的可能性很大,当且仅当它是成功获得的,等等。作为一般规则,只需使用synchronized,除非/直到您可以证明它为您的应用程序所需的吞吐量提供了重大瓶颈。

答案 3 :(得分:1)

java中的同步(技术上)不是拒绝拒绝其他线程访问对象,而是关于确保使用同步锁的线程之间(一次)对它的唯一使用。因此T2可以在T1具有同步锁定时访问该对象,但在T1释放之前将无法获得同步锁定。

答案 4 :(得分:1)

你没有锁定变量;你锁定一个保护的互斥锁 特定范围的代码。规则很简单:如果有任何线程 修改一个对象,并且多个线程访问它(for 任何原因),所有访问必须完全同步。通常 解决方案是定义一个互斥锁来保护变量,请求 锁定它,并在访问完成后释放锁。 当一个线程请求锁定时,它会被挂起直到该锁定 已被释放。

在C ++中,通常使用RAII来确保锁定 无论块如何退出,都会释放。在Java中 同步块将在开始时获取锁定 (等到它可用),然后离开锁 程序离开块(无论出于何种原因)。

答案 5 :(得分:1)

您是否考虑过使用AtomicReferenceArray? http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/AtomicReferenceArray.html它提供了一个#getAndSet方法,它提供了一种线程安全的原子方式来更新索引。

答案 6 :(得分:1)

T1 access element at index 0 first, then lock it.

首先锁定静态最终互斥变量,然后访问静态变量。

 static final Object lock = new Object();
 synchronized(lock) {
   // access static reference
 }

或更好地访问类引用

synchronized(YourClassName.class) {
     // access static reference
}