synchronized和Lock有什么不同呢?

书欣 Java面经 发布时间:2023-06-30 21:50:14 阅读数:17249 1
下文是日常面试中,常见的synchronized和Lock区别说明,如下所示

区别1:两者的使用方式不同

synchronized:
   是java中的关键字(类似于if...else...)
     synchronized获取锁以及释放锁由Java虚拟机(JVM)实现

ReentrantLock是类层面的实现:
   锁获取以及锁释放由用户自己操作
注意事项:
   ReentrantLock在lock()获取锁后
     必须手动unlock()释放锁
      释放锁的代码我们通常写在finally语句块中
/** 创建可重入锁 */
private static final ReentrantLock lock = new ReentrantLock();
 
public void demoSync() {
    synchronized (lock) {
        // 业务代码
    }
}
 
public void demoLock() {
    lock.lock();
    try {
        // 业务代码
    } finally {
        lock.unlock();
    }
}

区别二:灵活性

synchronized使用简单
   而
ReentrantLock锁机制给用户的使用提供了极大的灵活性。

ReentrantLock灵活性
   我们可以在Hashtable和ConcurrentHashMap两个容器中查看
    Hashtable中使用synchronized锁,对整张Hash表进行加锁
    ConcurrentHashMap则使用ReentrantLock实现锁分离
      锁只是segment(片段)

ConcurrentHashMap源码

/**
 * Stripped-down version of helper class used in previous version,
 * declared for the sake of serialization compatibility
 */
static class Segment<K,V> extends ReentrantLock implements Serializable {
    private static final long serialVersionUID = 2249069246763182397L;
    final float loadFactor;
    Segment(float lf) { this.loadFactor = lf; }
}
 
/**
 * Saves the state of the {@code ConcurrentHashMap} instance to a
 * stream (i.e., serializes it).
 * @param s the stream
 * @throws java.io.IOException if an I/O error occurs
 * @serialData
 * the key (Object) and value (Object)
 * for each key-value mapping, followed by a null Pair.
 * The key-value mappings are emitted in no particular order.
 */
private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException {
    // For serialization compatibility
    // Emulate segment calculation from previous version of this class
    int sshift = 0;
    int ssize = 1;
    while (ssize < DEFAULT_CONCURRENCY_LEVEL) {
        ++sshift;
        ssize <<= 1;
    }
    int segmentShift = 32 - sshift;
    int segmentMask = ssize - 1;
    @SuppressWarnings("unchecked")
    Segment<K,V>[] segments = (Segment<K,V>[])
        new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
    for (int i = 0; i < segments.length; ++i)
        segments[i] = new Segment<K,V>(LOAD_FACTOR);
    s.putFields().put("segments", segments);
    s.putFields().put("segmentShift", segmentShift);
    s.putFields().put("segmentMask", segmentMask);
    s.writeFields();
 
    Node<K,V>[] t;
    if ((t = table) != null) {
        Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
        for (Node<K,V> p; (p = it.advance()) != null; ) {
            s.writeObject(p.key);
            s.writeObject(p.val);
        }
    }
    s.writeObject(null);
    s.writeObject(null);
    segments = null; // throw away
}

区别三:锁策略

synchronized是不公平锁
  而
ReentrantLock可指定锁是公平的还是非公平的
   可使用ReentrantLock(boolean fair)构造方法fair指定公平策略
   当使用公平排序策略
    则fair参数为true

公平锁和非公平锁简介

公平锁
  公平锁是指多个线程按照申请锁的顺序来获取锁
   线程直接进入队列中排队,队列中的第一个线程才能获得锁

非公平锁
   非公平锁是多个线程加锁时直接尝试获取锁
    能抢到锁到直接占有锁
	抢不到才会到等待队列的队尾等待

区别四:等待/通知机制

synchronized 实现等待/通知机制通知的线程是随机
ReentrantLock 实现等待/通知机制可以有选择性地通知。

区别五:锁自身信息

ReentrantLock 提供给用户多种方法用于获取锁的信息
   如:
    可以获取 Lock 是否被当前线程获得
	Lock 被同一个线程调用了几次
	Lock 是否被任意线程获取等等
synchronized由JVM维护,所以操作的空间比较小
    也是由灵活性决定的
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaMianJing/202306/16881330436945.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者