浅谈Synchronized和Vector

本文详细解析了Vector类的实现原理,探讨了其与ArrayList的区别,重点介绍了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;
    }
Java中的`synchronized`关键字是一种内置的同步机制,用于控制多线程对共享资源的访问,确保线程安全。其底层原理替代方案是Java并发编程中的核心内容。 ### 原理 `synchronized`关键字的实现依赖于Java对象头中的**监视器锁(Monitor Lock)**[^1]。每个对象都有一个与之关联的监视器锁,线程在进入`synchronized`代码块或方法时,需要获取该对象的锁;退出时释放锁。这种机制确保了同一时间只有一个线程可以执行被`synchronized`保护的代码。 具体来说,`synchronized`的底层实现涉及**对象头中的Mark Word**,它存储了对象的锁状态信息。在JVM中,锁的状态会经历**无锁状态、偏向锁、轻量级锁重量级锁**四种状态的转换,这一过程由JVM根据竞争情况自动优化[^2]。例如,在没有竞争的情况下,JVM可能会使用偏向锁来减少不必要的同步操作,从而提升性能。 ### 作用 `synchronized`关键字可以实现以下功能[^3]: - **原子性**:确保一个操作或多个操作要么全部执行,要么全部不执行,中间不会被其他线程打断。 - **可见性**:保证线程在释放锁之前对共享变量的修改对其他线程可见。 - **有序性**:防止指令重排导致的问题,确保程序按照代码顺序执行。 ### 用法 `synchronized`可以用于修饰**方法**或**代码块**: - **实例方法**:锁是当前实例对象(`this`)。 - **静态方法**:锁是当前类的`Class`对象。 - **代码块**:可以指定锁对象,通常使用一个专门的锁对象以减少锁的持有时间[^4]。 示例代码如下: ```java public class SynchronizedExample { private final Object lock = new Object(); private int count = 0; public void increment() { synchronized (lock) { count++; } } public synchronized void decrement() { count--; } public static synchronized void staticMethod() { // 静态方法的锁是类的Class对象 } } ``` ### 替代方案 虽然`synchronized`是Java中最基础的同步机制,但在某些复杂场景下,它可能不够灵活。以下是一些常见的替代方案: 1. **`java.util.concurrent.locks.Lock`接口** `ReentrantLock`是`Lock`接口的一个实现,它提供了比`synchronized`更灵活的锁机制,支持尝试获取锁(`tryLock`)、超时、中断等操作。示例代码如下: ```java import java.util.concurrent.locks.ReentrantLock; public class LockExample { private final ReentrantLock lock = new ReentrantLock(); private int count = 0; public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } } ``` 2. **`java.util.concurrent`包中的并发工具** - **`CountDownLatch`**:允许一个或多个线程等待其他线程完成操作。 - **`CyclicBarrier`**:用于多个线程相互等待,直到所有线程都到达某个屏障点。 - **`Semaphore`**:控制同时访问的线程数量,适用于资源池、限流等场景。 3. **无锁编程与原子类** `java.util.concurrent.atomic`包提供了一系列原子操作类,如`AtomicInteger`、`AtomicLong`等,它们通过CAS(Compare and Swap)算法实现线程安全的操作,避免了锁的开销。示例代码如下: ```java import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerExample { private AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); } } ``` ### 性能优化 随着JDK的不断优化,`synchronized`的性能已大幅提升。JVM通过**锁消除(Lock Elimination)**、**锁粗化(Lock Coarsening)**、**偏向锁(Biased Locking)**等技术减少了锁的开销[^2]。因此,在简单的同步需求中,`synchronized`仍然是一个简洁高效的选择。 ### 适用场景 - **简单同步需求**:使用`synchronized`关键字即可满足需求。 - **复杂同步需求**:考虑使用`ReentrantLock`或`java.util.concurrent`包中的工具。 - **高性能需求**:优先考虑使用原子类或无锁编程技术。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Array_new

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

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

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

打赏作者

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

抵扣说明:

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

余额充值