Synchronized和Lock

2022-08-03 14:26:52 浏览数 (3)

锁的优化

Lock没有引入锁的升级这个概念,只有普通的自旋和偏向锁 synchronized 拥有锁的升级,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁 等技术来减少锁操作的开销。并且还会随着竞争的激烈而逐渐升级

可中断

synchronized 是不可以被中断的,但Lock是可以中断它的,Lock中断的代码见下方:

代码语言:javascript复制
package com.example.demo;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应,
 * 在一个线程等待锁的过程中,可以被打断
 */
public class 中断锁 {

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();

        Thread t1 = new Thread(() -> {
            try {
                lock.lock();
                System.out.println("t1 start");
                TimeUnit.SECONDS.sleep(5000);
                System.out.println("t1 end");
            } catch (InterruptedException e) {
                System.out.println("t1 interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            try {
                //lock.lock();
                lock.lockInterruptibly(); //可以对interrupt()方法做出响应
                System.out.println("t2 start");
                TimeUnit.SECONDS.sleep(5000);
                System.out.println("t2 end");
            } catch (InterruptedException e) {
                System.out.println("t2 interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t2.start();

        t1.interrupt(); //打断线程1的等待,无法打断,因为线程1是.lock()方法
        t2.interrupt(); //打断线程2的等待,可以打断,因为线程2是.lockInterruptibly()方法

    }
}
公平锁

Lock支持公平锁,synchronized 不支持公平锁

Lock支持更多场景

ReentrantReadWriteLock:可以对于读或者写进行自定义的锁 private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); //读锁 private final Lock w = rwl.writeLock(); //写锁 synchronized 锁只能同时被一个线程拥有,但是 Lock 锁没有这个限制 例如在读写锁中的读锁,是可以同时被多个线程持有的,可是 synchronized 做不到

应该选择synchronized还是应该选择Lock?

  • 如果能不用最好既不使用 Lock 也不使用 synchronized。因为在许多情况下你可以使用 java.util.concurrent 包中的机制,它会为你处理所有的加锁和解锁操作,也就是推荐优先使用工具类来加解锁
  • 如果 synchronized 关键字适合你的程序, 那么请尽量使用它,这样可以减少编写代码的数量,减少出错的概率。因为一旦忘记在 finally 里 unlock,代码可能会出很大的问题,而使用 synchronized 更安全
  • 如果特别需要 Lock 的特殊功能,比如尝试获取锁、可中断、超时功能等,才使用 Lock

0 人点赞