Java中的锁机制是多线程编程中常用的同步机制,主要用于控制共享资源的访问。Java中的锁分为悲观锁和乐观锁两种,本文将介绍它们的原理及实现方式。
悲观锁
悲观锁的基本思想是,当线程访问共享资源时,认为其他线程可能会修改数据,因此需要加锁保护共享资源。悲观锁实现起来比较简单,通常使用synchronized关键字来实现。
举个例子,假设有一个共享变量count,多个线程同时对它进行累加操作,代码如下:
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
上面的代码使用synchronized关键字对increment方法进行加锁,保证多个线程对count变量的访问是同步的。
乐观锁
乐观锁的基本思想是,当线程访问共享资源时,认为其他线程不会修改数据,因此不需要加锁,而是在更新数据时判断是否被其他线程修改过,如果没有被修改,则更新成功,否则需要重试。
乐观锁的实现方式有很多种,其中最常用的是基于版本号(Version Number)的乐观锁。每个共享数据都维护一个版本号,当线程更新数据时,先读取当前的版本号,然后尝试更新数据,如果版本号未发生变化,则更新成功,否则需要重试。
举个例子,假设有一个共享变量count,多个线程同时对它进行累加操作,代码如下:
public class Counter {
private int count = 0;
private int version = 0;
public void increment() {
int currentVersion = version;
while (true) {
if (compareAndSet(currentVersion)) {
count++;
break;
}
}
}
public int getCount() {
return count;
}
public synchronized boolean compareAndSet(int expectVersion) {
if (version == expectVersion) {
version++;
return true;
}
return false;
}
}
上面的代码使用compareAndSet方法实现了基于版本号的乐观锁。increment方法先读取当前的版本号,然后在一个while循环中不断尝试更新数据,如果compareAndSet方法返回true,则表示更新成功,否则需要继续重试。
总之,悲观锁和乐观锁是Java中常用的两种锁机制,悲观锁通过加锁保护共享资源,保证线程安全,而乐观锁则通过无锁编程的方式提高并发性能。开发人员需要根据实践场景选择适应的锁。