内部锁
在 Java 中,每个对象都有一个内部锁,也称为监视器锁或对象锁。内部锁是通过在代码块或方法前加上 synchronized
关键字来实现的。当一个线程执行一个带有 synchronized
关键字的方法或代码块时,它必须先获得该对象的内部锁,才能执行该方法或代码块。
同步代码块
synchronized(锁对象){
}
把同步代码块中的代码锁住,其中的代码只能让一个线程执行(在同一时间内)
必须保证 锁对象 总是同一个对象
想象 锁对象 代表一道门,没有线程进入时,门开着,一旦有线程A进入之后就会关上这扇门,其他线程就不能从这扇门进入同步代码块,当线程A执行完同步代码块中的内容离开就会重新打开这道门,其他线程才能够进入。
但如果其他线程B来的时候拿到的是另一个 锁对象 ,另一个 锁对象就好是另一扇门b, 这一扇门没有被关闭, 后来的线程B从 门b 就可以进入同步代码块,因此产生了不同步问题。
同步方法
同步方法的锁为调用方法的对象 this
静态方法不能使用this,那就是 this.class
Lock
Java中的Lock是一种用于控制多个线程访问共享资源的机制。与传统的同步块相比,Lock提供了更细粒度的线程控制,并且可以提供更多的灵活性和性能优势。
- Lock的定义与基本用法
Lock是Java提供的一种线程同步机制。与synchronized不同,Lock需要程序员手动申请和释放锁。Java中提供了两种类型的Lock:ReentrantLock和ReentrantReadWriteLock.ReadLock/WriteLock。其中,ReentrantLock是一个可重入的互斥锁,而ReentrantReadWriteLock则支持读写锁。
Lock lock = new ReentrantLock();
lock.lock();
try {
// 在锁定状态下执行线程安全的代码
} finally {
lock.unlock();
}
2 可中断锁
在某些情况下,线程需要能够响应中断请求,这时我们可以使用可中断锁。当一个线程正在等待获取锁的时候,如果接收到了中断请求,它可以选择放弃获取锁,而不是一直等待下去。
Lock lock = new ReentrantLock();
try {
lock.lockInterruptibly();
try {
// 在锁定状态下执行线程安全的代码
} finally {
lock.unlock();
}
} catch (InterruptedException e) {
// 处理中断异常
}
读写锁
Java 中的读写锁是一种特殊的锁,用于控制多个线程对共享资源的读和写。读写锁分为两种类型:读锁和写锁。读锁允许多个线程同时读取共享资源,而写锁只允许一个线程写入共享资源。如果一个线程获取了写锁,则其他线程不能读取或写入共享资源。
Java 中的 java.util.concurrent.locks.ReentrantReadWriteLock
类提供了读写锁的实现。该类有两个方法:readLock()
和 writeLock()
,分别返回读锁和写锁。获取读锁的线程可以同时读取共享资源,获取写锁的线程必须等待所有读锁释放后才能写入共享资源。
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class SharedData {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private int data = 0;
public void writeData(int newData) {
lock.writeLock().lock();
try {
data = newData;
} finally {
lock.writeLock().unlock();
}
}
public int readData() {
lock.readLock().lock();
try {
return data;
} finally {
lock.readLock().unlock();
}
}
}