Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 静态数组变量是否需要锁定?_Java_C++_Concurrency_Locking_Mutex - Fatal编程技术网

Java 静态数组变量是否需要锁定?

Java 静态数组变量是否需要锁定?,java,c++,concurrency,locking,mutex,Java,C++,Concurrency,Locking,Mutex,假设我有一个静态变量,它是一个大小为5的数组。 假设我有两个线程,T1和T2,它们都试图改变数组索引0处的元素。然后使用索引0处的元素。 在这种情况下,我应该锁定数组,直到T1使用完元素,对吗 另一个问题是假设T1和T2已经在运行,T1首先访问索引0处的元素,然后锁定它。但紧接着T2尝试访问索引0处的元素,但T1尚未解锁索引0。在这种情况下,为了让T2访问索引0处的元素,T2应该做什么?T2应该在T1解锁数组的索引0后使用回调函数吗 我应该锁定数组直到T1使用完元素,对吗 是的,为了避免比赛条件

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

另一个问题是假设T1和T2已经在运行,T1首先访问索引0处的元素,然后锁定它。但紧接着T2尝试访问索引0处的元素,但T1尚未解锁索引0。在这种情况下,为了让T2访问索引0处的元素,T2应该做什么?T2应该在T1解锁数组的索引0后使用回调函数吗

我应该锁定数组直到T1使用完元素,对吗

是的,为了避免比赛条件,这将是一个好主意

T2应该怎么做

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

示例代码:

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

public void modifyObject() {
    synchronized(lockObject) {
       // read or modify the objects
    }
}
从技术上讲,您还可以在阵列本身上进行同步

当有多个线程访问某个对象时,同步锁

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


如果您不希望线程阻塞,可以通过使用和使用非阻塞检查来实现更细粒度的控制。

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

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

如果希望在争用锁时对行为进行更细粒度的控制,可以使用显式对象。这些提供了带有超时和立即返回的tryLock方法,根据是否可以获得锁返回true或false。因此,如果没有立即获得锁,您可以测试返回值并采取任何您喜欢的操作,例如注册回调函数、递增计数器以及在重试之前向用户提供反馈等


但是,这种定制反应很少需要,并且显著增加了锁定代码的复杂性,更不用说如果忘记始终在finally块中释放锁(如果且仅当成功获取锁时)会发生错误的可能性很大等等,只要使用synchronized,除非/直到您能够证明它为您的应用程序所需的吞吐量提供了一个显著的瓶颈。

java中的同步从技术上讲不是拒绝其他线程访问对象,而是确保在使用同步锁的线程之间一次性唯一地使用对象。因此,T2可以在T1具有同步锁的情况下访问对象,但在T1释放同步锁之前,T2将无法获得同步锁。

您不锁定变量;您锁定了一个互斥锁,它可以保护 特定范围的代码。规则很简单:如果有线程 修改一个对象,并且有多个线程访问该对象 无论出于何种原因,所有访问都必须完全同步。照常 解决方案是定义一个互斥来保护变量request 一把锁放在上面,一旦进入完毕就释放锁。 当一个线程请求一个锁时,它将被挂起,直到该锁发出 他被释放了

在C++中,通常使用RAII来确保锁是 释放,无论块如何退出。在爪哇, 同步块将在开始时获取锁 等待它可用,并在
程序出于任何原因离开块。

您考虑过使用原子引用阵列吗?它提供了一个getAndSet方法,该方法提供了一种线程安全的原子方法来更新索引

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
}