使用Java锁可以保证多线程下的数据访问与操作的线程安全性,下面详细讲解如何使用Java锁。
1. Java锁的基本使用
Java提供了几种类型的锁:
- synchronized关键字:synchronized关键字可以锁住代码块或方法,保证同一时刻只有一个线程可以执行锁住的代码
- ReentrantLock类:ReentrantLock是Java提供的一种可重入锁,可以更灵活地控制代码块的锁定与解锁
下面分别介绍这两种锁的基本使用。
1.1 synchronized关键字
synchronized关键字的基本使用形式如下:
synchronized (lock) {
// 锁住的代码块
}
其中,lock通常是一个对象,表示当前锁的锁对象,下面举一个简单的示例:
public class Counter implements Runnable {
private int count = 0;
@Override
public synchronized void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(counter);
Thread t2 = new Thread(counter);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.count);
}
}
这个示例中,我们创建了一个计数器对象Counter,使用两个线程对Counter对象进行计数,可以看到count的最终值应该为两个线程中递增了10000次的结果,即20000。
1.2 ReentrantLock类
ReentrantLock类提供了一种比synchronized更灵活的方式来控制代码块的锁定与解锁,基本使用形式如下:
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 锁住的代码块
} finally {
lock.unlock();
}
其中,lock()用于锁定代码块,unlock()用于解锁代码块。
下面举一个简单的示例:
public class Counter implements Runnable {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 10000; i++) {
count++;
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(counter);
Thread t2 = new Thread(counter);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.count);
}
}
这个示例与前面的示例功能相同,只是使用了ReentrantLock来实现锁。
2. Java锁的高级使用
Java还提供了一些高级的锁,例如Semaphore、ReadWriteLock、StampedLock等。
2.1 Semaphore类
Semaphore是一种计数信号量,可以控制同时执行的线程数量,基本使用形式如下:
Semaphore semaphore = new Semaphore(n);
semaphore.acquire();
try {
// 获得信号量的线程可以执行的代码块
} finally {
semaphore.release();
}
其中,n表示并发访问的最大线程数量,acquire()方法用于获得信号量,release()方法用于释放信号量。
下面举一个简单的示例:
public class ConnectionPool {
private int size;
private List<Connection> connections;
private Semaphore semaphore;
public ConnectionPool(int size) {
this.size = size;
connections = new ArrayList<>(size);
semaphore = new Semaphore(size);
for (int i = 0; i < size; i++) {
connections.add(new Connection());
}
}
public Connection getConnection() throws InterruptedException {
semaphore.acquire();
return connections.remove(0);
}
public void releaseConnection(Connection conn) {
connections.add(conn);
semaphore.release();
}
private static class Connection {
public void doSomething() {
System.out.println("Connection is doing something...");
}
}
public static void main(String[] args) throws InterruptedException {
ConnectionPool pool = new ConnectionPool(10);
for (int i = 0; i < 20; i++) {
new Thread(() -> {
try {
Connection conn = pool.getConnection();
conn.doSomething();
pool.releaseConnection(conn);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
这个示例中,我们创建了一个连接池,使用Semaphore来实现对连接数量的控制。
2.2 ReadWriteLock类
ReadWriteLock是一种支持读写锁的锁机制,可以控制同时读取资源的线程数量,基本使用形式如下:
ReadWriteLock lock = new ReentrantReadWriteLock();
// 读锁定
lock.readLock().lock();
try {
// 读锁定的代码块
} finally {
lock.readLock().unlock();
}
// 写锁定
lock.writeLock().lock();
try {
// 写锁定的代码块
} finally {
lock.writeLock().unlock();
}
其中,readLock()返回读锁对象,writeLock()返回写锁对象。
下面举一个简单的示例:
public class Counter {
private int count = 0;
private ReadWriteLock lock = new ReentrantReadWriteLock();
public int getCount() {
lock.readLock().lock();
try {
return count;
} finally {
lock.readLock().unlock();
}
}
public void increment() {
lock.writeLock().lock();
try {
count++;
} finally {
lock.writeLock().unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.getCount());
}
}
这个示例中,我们创建了一个计数器对象Counter,使用两个线程对Counter对象进行计数,但是我们使用了ReadWriteLock来锁定读取数据和写入数据的代码块,因此可以在最终输出计数器的值时保证线程安全性。
至此,我们对Java锁的基本使用和高级使用进行了讲解,希望对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何使用Java锁? - Python技术站