所以我想说我有一个静态变量,它是一个大小为5的数组。 让我们说我有两个线程,T1和T2,它们都试图改变该数组的索引0处的元素。然后使用索引0处的元素。 在这种情况下,我应该使用右边的元素锁定数组,直到T1完成?
另一个问题是让我们说T1和T2已经在运行,T1访问元素首先在索引0,然后锁定它。但是在T2尝试访问索引0处的元素之后,T1还没有解锁索引0。那么在这种情况下,为了让T2访问索引0处的元素,T2应该做什么? T1解锁数组索引0后T2应该使用回调函数吗?
答案 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
方法(两者都有超时,并立即返回),根据是否可以获得锁定,返回true
或false
。因此,如果没有立即获得锁定,您可以测试返回值并采取您喜欢的任何操作(例如注册回调函数,递增计数器并在再次尝试之前向用户提供反馈等)。
然而,这种自定义反应很少是必要的,并且显着增加了锁定代码的复杂性,更不用说如果您忘记始终在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
}