1. CAS(Compare and Swap,比较并交换 )
- 原理:CAS 操作包含三个操作数 —— 内存地址(V)、预期原值(A)和新值(B)。如果内存地址 V 处的值等于预期原值 A,则将该地址处的值更新为新值 B,否则不做操作 。它是通过 CPU 指令实现原子性操作,操作系统封装指令形成系统 API,Java 又对 API 进行封装 。伪代码如下:
boolean CAS(address, expectValue, swapValue) {
if (address == expectValue) {
address = swapValue;
return true;
}
return false;
}
- 应用场景
- 实现原子类:比如 AtomicInteger 类,通过 CAS 实现原子的自增、自减等操作。Java 中定义一个 AtomicInteger 类型的变量 count 并初始化为 0 : private static AtomicInteger count = new AtomicInteger(0); , count++ 操作在底层就是利用 CAS 实现线程安全的自增 。
- 实现自旋锁:例如自定义的自旋锁 SpinLock ,通过 CAS 操作来判断和设置锁的状态 。
public class SpinLock {
private Thread owner;
public void lock() {
while (!CAS(this.owner, null, Thread.currentThread())) {
// 自旋等待
}
}
public void unlock() {
this.owner = null;
}
private boolean CAS(Thread expected, Thread newThread) {
// 实际的 CAS 操作,这里只是示意
if (this.owner == expected) {
this.owner = newThread;
return true;
}
return false;
}
}
- ABA 问题:当通过 CAS 来判定当前值是否被其他线程修改时,如果一个值原来是 A,被改成了 B,又改回了 A ,此时 CAS 感知不到变化,但可能会导致问题。解决方法可以引入版本号,每次修改版本号加 1 ,CAS 比较时同时比较版本号 。
2. synchronized
- 原理:它是 Java 的关键字,底层是在 JVM 内部通过 C++ 实现。synchronized 优化体现在锁升级(无锁 -> 偏向锁 -> 自旋锁 -> 重量锁)、锁消除(JVM 检测到不需要加锁的情况自动去除锁)、锁粗化(将多个连续的加解锁操作合并为一个范围更大的加解锁操作 ) 。
- 示例代码
public class SynchronizedExample {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
}
3. ReentrantLock
- 原理:是一个可重入的互斥锁,与 synchronized 相比,功能更丰富。它是通过 AQS(AbstractQueuedSynchronizer,抽象队列同步器)来实现的 。
- 特点
- 可重入性:同一个线程可以多次获取锁 。
- 提供了公平锁和非公平锁的实现(默认非公平锁 ) 。
- 具有 tryLock() 方法,尝试获取锁,获取失败可以立即返回或者等待一段时间返回 。
- 示例代码
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public boolean tryIncrement() {
if (lock.tryLock()) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
}
4. 线程创建方式
- 继承 Thread 类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running");
}
}
// 使用方式
MyThread myThread = new MyThread();
myThread.start();
- 实现 Runnable 接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running");
}
}
// 使用方式
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
- 基于 lambda 表达式(本质也是实现 Runnable )
Thread lambdaThread = new Thread(() -> System.out.println("Lambda Thread running"));
lambdaThread.start();
- 实现 Callable 接口
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 100;
}
}
// 使用方式
MyCallable myCallable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
Thread callableThread = new Thread(futureTask);
callableThread.start();
try {
Integer result = futureTask.get();
System.out.println("Callable result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
- 基于线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> System.out.println("Task in thread pool running"));
}
executorService.shutdown();
}
}