浅谈Synchronized和Vector

浅谈Synchronized和Vector

在学习集合源码时,我们不可避免的都会遇到synchronized关键字,正是有了这个关键字才让我们的Vector实现线程安全,而且Vector大部分的源码也和ArrayList的源码比较相似。

Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:

  • Vector 是同步访问的。
  • Vector 包含了许多传统的方法,这些方法不属于集合框架。

Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。

首先我们来说一下synchronized的作用:

1.原子性:那么所谓的原子性是指一个或多个操作要么全部执行,要么全部不被执行。而被synchronized修饰的类或对象都是原子的,因为操作之前都要先获取类或对象的锁,直到执行完毕才能被释放。

2.可见性:可见性是指多个线程访问一个资源时,该资源的状态、值等信息对于其他的线程都是可见的

3.有序性:有序性值程序的执行顺序按照代码先后执行, synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。

Vector添加元素:

/**
 * 将指定的元素附加到Vector的末尾。
 *
 * @param e 元素要附加到这个Vector
 * @return {@code true} (as specified by {@link Collection#add})
 * @since 1.2
 */
public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}
/**
     * Inserts the specified object as a component in this vector at the
     * specified {@code index}. Each component in this vector with
     * an index greater or equal to the specified {@code index} is
     * shifted upward to have an index one greater than the value it had
     * previously.
     *
     * <p>The index must be a value greater than or equal to {@code 0}
     * and less than or equal to the current size of the vector. (If the
     * index is equal to the current size of the vector, the new element
     * is appended to the Vector.)
     *
     * <p>This method is identical in functionality to the
     * {@link #add(int, Object) add(int, E)}
     * method (which is part of the {@link List} interface).  Note that the
     * {@code add} method reverses the order of the parameters, to more closely
     * match array usage.
     *
     * @param      obj     the component to insert
     * @param      index   where to insert the new component
     * @throws ArrayIndexOutOfBoundsException if the index is out of range
     *         ({@code index < 0 || index > size()})
     将指定的对象作为组件插入到此向量中指定的{@code索引}处。该向量中索引大于或等于指定的{@code index}的每个组件的索引都向上移动,使其索引值比之前的值大1。
     */
public synchronized void insertElementAt(E obj, int index) {
    modCount++;
    if (index > elementCount) {
        throw new ArrayIndexOutOfBoundsException(index
                                                 + " > " + elementCount);
    }
    ensureCapacityHelper(elementCount + 1);
    System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
    elementData[index] = obj;
    elementCount++;
}

删除元素:

/**如果Vector中不包含该元素,则保持不变。更正式地说,删**除索引i最低的元素,使(o==null ?Get (i)==null: **o.equals(Get (i)))(如果存在这样的元素)。如果Vector中**包含指定的元素,则返回:true
**/
public boolean remove(Object o) {
    return removeElement(o);
}
public synchronized boolean removeElement(Object obj) {
    modCount++;
    int i = indexOf(obj);
    if (i >= 0) {
        removeElementAt(i);
        return true;
    }
    return false;
}
public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    int j = elementCount - index - 1;
    if (j > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    elementCount--;
    elementData[elementCount] = null; /* to let gc do its work */
}

获取元素:

public synchronized E get(int index) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

    return elementData(index);
}

插入元素:

public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
### 比较 `synchronized` 关键字 `ReentrantLock` 类 #### 锁机制的不同实现方式 `synchronized` 是一种内置的关键字,用于提供隐式的锁机制。当一个方法或代码块被声明为 `synchronized` 时,它自动获取当前对象的内在锁(intrinsic lock),并在执行完毕后释放这个锁[^3]。 ```java public synchronized void methodA() { // 执行一些操作 } ``` 相比之下,`ReentrantLock` 提供了一种显式的锁机制。开发者需要手动创建 `ReentrantLock` 对象,并通过调用其 `lock()` `unlock()` 方法来控制资源访问: ```java private final ReentrantLock lock = new ReentrantLock(); public void methodB() { lock.lock(); try { // 执行一些操作 } finally { lock.unlock(); } } ``` #### 性能差异 通常情况下,在低竞争环境下两者性能相近;但在高并发场景下,`ReentrantLock` 可能表现出更好的吞吐量,因为它支持更灵活的加锁策略以及公平/非公平模式的选择[^2]。 #### 功能特性对比 - **可中断等待**:`ReentrantLock` 支持尝试获取锁(`tryLock`) 或者带有超时参数的方法 (`tryLock(long timeout, TimeUnit unit)`), 这使得线程可以在无法获得锁的情况下选择其他行为而不是无限期地挂起。 - **条件变量**:借助于 `Condition` 接口,可以实现更加复杂的协调逻辑,比如生产者消费者模型中精确的通知特定类型的事件发生。 - **重入性**:二者都允许同一个线程多次进入已持有的锁区域而不会造成死锁现象。 #### 使用建议 对于简单的同步需求,推荐使用 `synchronized` ,因为它的语法简洁明了不易出错。而对于复杂的应用场景,则应考虑采用功能更为强大的 `ReentrantLock` 来满足业务要求并提高程序效率[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Array_new

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值