Java 同步如何使向量线程安全?

Java 同步如何使向量线程安全?,java,vector,arraylist,Java,Vector,Arraylist,现在我们知道数组列表是不同步的,而向量是同步的。但这种同步如何使向量线程安全呢?举例说明,如果您没有“同步”,它将使线程安全,这将非常有帮助。您可能面临的一个常见且令人沮丧的问题是竞争条件(调试时真的很痛苦!) 详情如下: 下面是另一个线程,它解释了“synchronized”关键字在java中的作用。 我认为这条线索中的答案比我自己解释得更好: 为了简单起见,让我们假设以下是在数组中插入元素的代码 void insert(int element) { elements[this.len

现在我们知道数组列表是不同步的,而向量是同步的。但这种同步如何使向量线程安全呢?举例说明,如果您没有“同步”,它将使线程安全,这将非常有帮助。您可能面临的一个常见且令人沮丧的问题是竞争条件(调试时真的很痛苦!) 详情如下:

下面是另一个线程,它解释了“synchronized”关键字在java中的作用。 我认为这条线索中的答案比我自己解释得更好:

为了简单起见,让我们假设以下是在数组中插入元素的代码

void insert(int element)
{
    elements[this.length] = element;
    this.length++;
}
现在让我们假设有两个线程试图在数组中插入一个元素

thread1.insert(5);
thread2.insert(7);
Array contents = [1,2,3,4] and length = 4
考虑上述方法不同步。因此,下面的场景将打乱数组的内容

thread1.insert(5);
thread2.insert(7);
Array contents = [1,2,3,4] and length = 4
也就是说,thread1执行方法的第一条语句,并将执行转移到第二条线程。现在数组内容变为

Array contents = [1,2,3,4,5] but length is still 4
现在,thread2完全执行insert

Array contents = [1,2,3,4,7] and length = 5 *Error*
现在thread1完成了该方法,最后的内容是

Array contents = [1,2,3,4,7] and length = 6
但是,如果将insert方法定义为同步,则同一对象上的两个同步方法不能同时运行。因此,当thread2调用insert时,它会发现thread1有一个锁,它会等待thread1完成。因此,您不会得到过时的数据

如果同步始终是安全的,为什么我们还要使用非同步方法?

原因是,JVM在锁定和解锁对象方面有额外的开销。因此,在这里使用非同步方法的权衡是,您的处理时间会稍微好一点


如果您查看一下源代码,就会发现所有重要的方法都被定义为同步的。因此使它们具有线程安全性。

如您所知,synchronized关键字确保只有一个线程可以输入这样一个受保护的代码段,因为只有一个线程可以保存对象的监视器

另一方面,线程安全机制要复杂得多。它通常覆盖多个对象

但是回到
向量
。不同步
get
方法可能会导致以下问题:

  • 线程A使用等于元素计数的索引进入get方法。检查并证明if状况正常。没有抛出异常
  • 此时线程B获得处理器时间。线程A被设置为等待状态。线程B进入完全运行的remove方法。现在删除一个元素,元素计数递减1
  • 现在线程再次获取处理器并继续执行行
    return elementData(index)
    。这将返回
    null
    ,因为删除已用
    null
    覆盖该位置

  • 因此,同步这些方法使Vector确实有点线程安全。但是,如果您的程序需要更高的线程安全性,您通常会通过对向量(以及其他对象)的多次调用来同步整个代码块。

    您知道什么是
    synchronized
    吗?是的,我知道,它就像一个锁,如果一个线程正在调用对象的同步方法,那么具有相同对象的其他线程无法调用另一个线程或具有同步关键字的相同方法,那么这在这里是如何应用的呢?这就是我想知道的,两个线程想将向量元素的值设置在位置2,哪个线程会成功?该位置的元素将具有哪个值?