Java中的锁

本文详细介绍了乐观锁和悲观锁的工作原理及应用场景,并对比了volatile与synchronized的区别。此外,还探讨了Java中锁的不同状态,AQS框架的作用以及可重入锁的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 乐观锁:每次共享数据的时候认为别人不会修改, 只更新的时候去判断这期间有没有人去更新数据。数据库版本号和通过CAS算法实现的类。

2.悲观锁:假设每次拿数据的时候都会被其他人修改,在每次共享数据的时候加锁,使用完了再释放。Java中的synchronize重量级锁和数据库行锁。

3 volatile与synchronized区别:synchronized用于加锁,volatile只是保持变量的可见性,适用一个线程写,多个线程读的场景,只能保证线程可见性,不能保证原子性。volatile防止指令重排,在DCL(双重检查锁模式)中,防止高并发的情况下,指令重排造成的线程安全问题。  private volatile static Singleton singleton;

4.Java 中的说就是在对象的Markword中的记录一个锁状态。 无锁,偏向锁,轻量级锁(自旋锁 -> 自适应自旋锁 解决的是“锁竞争时间不确定”的问题),重量级锁对应不同的四个状态。

5.AQS(AbstractQueueSynchroizer): 是Java线程同步的框架,维护一个信号量state和一个线程组成的双向链表队列,用于给线程排队。state类似于红绿灯,控制线程排队或者放行。

6. 可重入锁:某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。通过信号量实现。例如:synchronized  ReentrantLock

### 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值