Java中的两个一样的锁
在多线程编程中,锁是一种用来协调对共享资源访问的机制。Java提供了多种锁的实现方式,其中最常见的是Synchronized
关键字和ReentrantLock
类。在这篇文章中,我们将讨论“两个一样的锁”这一概念,分析如何在Java中使用它们,以及它们的不同之处。
锁的基本概念
在Java中,锁用于保证在多线程环境下,多个线程不能同时访问某个共享资源。每个锁可以被视作一个“开关”,只有持有该锁的线程可以执行相应的代码。为了更好地理解这一概念,看看下图的类图:
classDiagram
class Lock {
+void lock()
+void unlock()
}
class SynchronizedLock {
+synchronized void method1()
}
class ReentrantLock {
+void lock()
+void unlock()
}
Lock <|-- SynchronizedLock
Lock <|-- ReentrantLock
Synchronized关键字
Synchronized
是Java中最常用的同步方式,它可以用在方法或代码块上。当一个线程访问被synchronized
修饰的方法时,其他线程会被阻塞,直到该线程释放锁。
示例代码
public class SynchronizedExample {
private static int count = 0;
public synchronized void increment() {
count++;
}
public static void main(String[] args) {
SynchronizedExample example = new SynchronizedExample();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + count);
}
}
在上述代码中,increment
方法是被synchronized
修饰的,因此当一个线程在执行这个方法时,另一个线程无法进入。
ReentrantLock类
ReentrantLock
是Java提供的一种显示锁,它提供了比synchronized
更高级的功能,如尝试锁定、定时锁等。ReentrantLock
也允许线程在中断时返回,从而提升了灵活性。
示例代码
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockExample example = new ReentrantLockExample();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + count);
}
}
这里使用ReentrantLock
实现了与synchronized
相同的功能。无论是synchronized
还是ReentrantLock
,它们的目的都是为了确保对共享资源的安全访问。
结论
在Java中,虽然synchronized
和ReentrantLock
都是用来解决多线程竞争的问题,但它们各有优势。Synchronized
易用且简洁,而ReentrantLock
则提供了更大的灵活性和功能。在选择使用哪种锁时,开发者需要根据具体情况作出权衡。理解这两者的工作机制和特性,能帮助我们编写更安全、高效的多线程代码。