(Java中使用常用的锁使用方式来保证线程安全)
在Java中,常用的锁使用方式主要有synchronized关键字和Lock接口。
1. 使用synchronized关键字:
synchronized关键字可以用来修饰方法或代码块,在修饰方法时,它将整个方法体作为临界区,保证同一时间只有一个线程可以执行该方法;在修饰代码块时,需要指定一个对象作为锁,同一时间只有获取锁的线程可以执行代码块。
示例代码:
public class SynchronizedExample {
private int count = 0;
public synchronized void increment() {
count++;
}
public static void main(String[] args) throws InterruptedException {
final SynchronizedExample example = new SynchronizedExample();
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
example.increment();
}).start();
}
Thread.sleep(2000); // 等待所有线程执行完毕
System.out.println(example.count);
}
}
在上述例子中,每个线程都调用了increment()
方法对count
进行加一操作,由于increment()
方法被synchronized
修饰,保证了每个线程在执行该方法时都会获取到锁,从而保证了线程安全。
2. 使用Lock接口:
Lock接口是Java.util.concurrent包中用于实现锁的接口。与synchronized关键字相比,Lock接口提供了更加灵活和可扩展的锁机制,例如可重入锁、读写锁等。
示例代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
final LockExample example = new LockExample();
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
example.increment();
}).start();
}
Thread.sleep(2000); // 等待所有线程执行完毕
System.out.println(example.count);
}
}
在上述例子中,使用了ReentrantLock作为锁的实现类,通过调用lock()
和unlock()
方法来获取和释放锁。与synchronized关键字不同,Lock接口提供了显式地获取锁和释放锁的机制,可以更加灵活地控制锁的使用。
无论是synchronized关键字还是Lock接口,它们的目的都是为了保证同一时间只有一个线程可以访问临界区,从而保证线程安全。