Java中的锁

Java中的锁

  • 公平锁/非公平锁
  • 可重入锁
  • 独享锁/共享锁
  • 互斥锁/读写锁
  • 乐观锁/悲观锁
  • 分段锁
  • 偏向锁/轻量级锁/重量级锁
  • 自旋锁

上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。

公平锁/非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS(AbstractQueuedSynchronizer)的来实现线程调度,所以并没有任何办法使其变成公平锁。

可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。说的有点抽象,下面会有一个代码的示例。对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁,其名字是Re entrant Lock重新进入锁。对于Synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。

synchronized void setA() throws Exception{
   
    Thread.sleep(1000);
    setB();
}
synchronized void setB() throws Exception{
   
    Thread.sleep(1000);
}

上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,setB可能不会被当前线程执

### Java 中的机制及类型 #### 显式 (Explicit Lock) 显式通过 `java.util.concurrent.locks.Lock` 接口及其具体实现类提供了一种更灵活的方式来管理线程间的同步[^1]。常见的实现类有 `ReentrantLock` 和 `ReadWriteLock`。与内置不同的是,显式允许开发人员更加精细地控制的行为,例如支持可中断等待、超时获取以及公平等功能。 以下是显式的一个简单示例: ```java import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ExplicitLockExample { private final Lock lock = new ReentrantLock(); public void performTask() { lock.lock(); // 获取 try { System.out.println(Thread.currentThread().getName() + " is performing the task."); } finally { lock.unlock(); // 释放 } } public static void main(String[] args) throws InterruptedException { ExplicitLockExample example = new ExplicitLockExample(); Thread t1 = new Thread(example::performTask, "Thread-1"); Thread t2 = new Thread(example::performTask, "Thread-2"); t1.start(); t2.start(); t1.join(); t2.join(); } } ``` #### 内置 (Synchronized Lock) 内置是一种隐式的定机制,在 Java 的语法层面由关键字 `synchronized` 提供支持[^2]。当一个方法或者代码块被声明为 `synchronized` 时,意味着同一时刻只允许一个线程执行该方法或代码块。这种机制适用于简单的场景,但对于复杂的多线程环境可能显得不够灵活。 下面是一个使用内置的例子: ```java public class SynchronizedLockExample { private int counter = 0; public synchronized void incrementCounter() { // 使用 synchronized 关键字 counter++; System.out.println(Thread.currentThread().getName() + ": Counter value -> " + counter); } public static void main(String[] args) throws InterruptedException { SynchronizedLockExample example = new SynchronizedLockExample(); Thread t1 = new Thread(() -> example.incrementCounter(), "Thread-1"); Thread t2 = new Thread(() -> example.incrementCounter(), "Thread-2"); t1.start(); t2.start(); t1.join(); t2.join(); } } ``` #### 常见类型 除了上述提到的显式和内置外,还有一些特定用途的: 1. **重入 (ReentrantLock)** 这是最常用的显式之一,允许多次进入同一个而不会死。它还支持公平性和非公平性的选项[^3]。 2. **读写 (ReadWriteLock)** 此类型的分为读和写两部分。多个线程可以同时持有读,但如果有一个线程持有了写,则不允许其他任何线程再获得读或写。这非常适合于那些读操作远大于写操作的应用程序。 3. **自旋 (SpinLock)** 自旋并不真正挂起线程而是让其忙等待直到可以获得为止。这种方式通常用于非常短时间内的竞争情况以减少上下文切换开销。 4. **信号量 (Semaphore)** 虽然严格意义上来说不算作传统意义上的“”,但它确实能用来协调对有限数量资源的竞争访问问题。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@程序员小袁

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

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

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

打赏作者

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

抵扣说明:

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

余额充值