synchronized与lock的区别
synchronized与lock的区别
引言
在多线程编程中,为了保证多个线程对共享资源的访问的正确性和一致性,需要使用线程加锁的机制。线程加锁可以避免多个线程同时访问共享资源而导致的数据竞争、不确定性和错误结果等问题。本文将介绍线程加锁的几种常见方式,并重点对比synchronized和lock两种常用的线程加锁机制的区别。
1. 线程加锁的方式
1.1 synchronized关键字
synchronized是Java中最基本、最常用的线程加锁机制。它可以修饰方法或代码块,用来实现对共享资源的访问控制。
1.1.1 synchronized修饰方法
当synchronized修饰一个方法时,表示该方法是一个同步方法。在调用该方法时,会自动获取该方法所属对象的锁,其他线程必须等待锁释放后才能访问该方法。
示例代码如下:
public class SynchronizedDemo {
private int count = 0;
public synchronized void increment() {
count++;
}
}
1.1.2 synchronized修饰代码块
当synchronized修饰一个代码块时,需要指定一个对象作为锁。在执行到该代码块时,线程会尝试获取该对象的锁,其他线程必须等待锁释放后才能访问该代码块。
示例代码如下:
private Object lock = new Object();
private int count = 0;
public void increment() {
synchronized (lock) {
count++;
}
}
}
1.2 lock接口
lock接口是Java.util.concurrent包中提供的一种更加灵活、可扩展的线程加锁机制。相比于synchronized关键字,lock接口提供了更多的功能和更细粒度的控制。
1.2.1 ReentrantLock类
ReentrantLock是lock接口的一个实现类,它实现了与synchronized相同的线程加锁功能,并且提供了更多的扩展功能。
示例代码如下:
private Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
1.2.2 ReadWriteLock接口
ReadWriteLock接口是Java中用于实现读写锁的接口,它提供了读锁和写锁的机制,以允许多个线程同时读取共享资源,但只允许一个线程进行写操作。
下面是一个简单的ReadWriteLock接口的实现示例:
public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
}
在这个示例中,ReadWriteLock接口定义了两个方法:readLock()
和writeLock()
,分别返回读锁和写锁的实例。
接下来,我们可以实现一个具体的ReadWriteLock接口,例如使用ReentrantReadWriteLock类:
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyReadWriteLock implements ReadWriteLock {
private final ReentrantReadWriteLock lock;
public MyReadWriteLock() {
lock = new ReentrantReadWriteLock();
}
@Override public Lock readLock() {
return lock.readLock();
}
@Override public Lock writeLock() {
return lock.writeLock();
}
}
在这个示例中,我们使用ReentrantReadWriteLock类来实现ReadWriteLock接口。在构造函数中,我们创建了一个ReentrantReadWriteLock实例。然后,我们通过实现readLock()和writeLock()方法,将对应的读锁和写锁返回。
使用这个自定义的ReadWriteLock实现,我们可以在多线程环境中进行读写锁的使用。例如:
private static final ReadWriteLock rwLock = new MyReadWriteLock();
private static final Lock readLock = rwLock.readLock();
private static final Lock writeLock = rwLock.writeLock();
public static void main(String[] args) {
// 在读操作中使用读锁 new Thread(() -> {
readLock.lock();
try {
// 执行读操作
} finally {
readLock.unlock();
}
}).start();
// 在写操作中使用写锁
new Thread(() -> {
writeLock.lock();
try {
// 执行写操作 } finally {
writeLock.unlock();
}
}).start();
}
}
在这个示例中,我们创建了一个Main类,并在main()方法中创建了两个线程。一个线程使用读锁进行读操作,另一个线程使用写锁进行写操作。
- 点赞
- 收藏
- 关注作者
评论(0)