java面试题-Java中有哪些无锁技术来解决并发问题?如何使用?
在Java中,除了传统的加锁机制(synchronized、Lock)外,还存在一些无锁技术,用于解决并发问题。这些技术包括原子工具类、线程本地存储、Copy-On-Write等。本教程将详细介绍这些无锁技术,并通过实例演示展示如何使用它们。
1. 原子工具类
Java提供了java.util.concurrent.atomic
包,其中的类都是原子类,基于sun.misc.Unsafe
实现。这些类利用CAS(Compare And Swap)指令保证了操作的原子性。以下是常见的原子工具类:
1.1 原子性基本数据类型
AtomicBoolean
AtomicInteger
AtomicLong
1.2 原子性对象引用类型
AtomicReference
AtomicStampedReference
AtomicMarkableReference
1.3 原子性数组
AtomicIntegerArray
AtomicLongArray
AtomicReferenceArray
1.4 原子性对象属性更新器
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
1.5 原子性累加器
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder
示例:使用AtomicInteger
实现原子操作
import java.util.concurrent.atomic.AtomicInteger;
public class TestAtomicInteger {
static volatile AtomicInteger atomicInteger = new AtomicInteger(0);
static volatile int i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int j = 0; j < 10000; j++) {
atomicInteger.incrementAndGet();
i++;
}
System.out.println("Thread t1 completed adding 10000");
});
Thread t2 = new Thread(() -> {
for (int j = 0; j < 10000; j++) {
atomicInteger.incrementAndGet();
i++;
}
System.out.println("Thread t2 completed adding 10000");
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("AtomicInteger: " + atomicInteger.get());
System.out.println("i: " + i);
}
}
通过AtomicInteger
保证了对共享变量的原子操作。
2. 线程本地存储
java.lang.ThreadLocal
类用于线程本地化存储,为每个线程创建一个变量,只有本线程可以在该变量中查看和修改值。这在数据库事务等场景中得到广泛应用。
示例:使用ThreadLocal
实现线程本地存储
public class TestThreadLocal {
private static final ThreadLocal<Integer> THREAD_LOCAL_NUM = ThreadLocal.withInitial(() -> 0);
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
Thread t = new Thread(TestThreadLocal::add10ByThreadLocal);
t.start();
}
}
private static void add10ByThreadLocal() {
try {
for (int i = 0; i < 3; i++) {
Integer n = THREAD_LOCAL_NUM.get();
n++;
THREAD_LOCAL_NUM.set(n);
System.out.println(Thread.currentThread().getName() + " : ThreadLocal num=" + n);
}
} finally {
THREAD_LOCAL_NUM.remove();
}
}
}
每个线程都能独立修改ThreadLocal
变量,保证了线程安全。
3. Copy-On-Write
Copy-On-Write
机制通过全量复制数组的方式来实现,并包括CopyOnWriteArrayList
和CopyOnWriteArraySet
等。这种机制适用于写操作较少的场景,但需要注意可能带来的内存消耗。
示例:使用CopyOnWriteArrayList
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestCopyOnWrite {
private static final Random R = new Random();
private static CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<>();
public static void main(String[] args) throws InterruptedException {
List<Thread> threadList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
Thread t = new Thread(() -> {
for (int j = 0; j < 5; j++) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
cowList.add(R.nextInt(100));
}
});
t.start();
threadList.add(t);
}
for (Thread t : threadList) {
t
.join();
}
System.out.println(cowList.size());
}
}
这里展示了CopyOnWriteArrayList
的用法,确保了写操作的线程安全性。
4. 其他并发工具类
Java中还存在一系列以"Concurrent"开头的并发工具类,例如ConcurrentHashMap
、ConcurrentLinkedDeque
、ConcurrentLinkedQueue
等。它们提供了更多复杂场景下的解决方案。
本教程深入讨论了Java中的无锁技术,包括原子工具类、线程本地存储、Copy-On-Write等,并通过实例演示了它们的使用。了解这些技术,可以更好地处理并发编程中的各种挑战,提高程序的性能和稳定性。
- 本文标签: Java 面试题
- 本文链接: https://www.jietongc.com/article/83
- 版权声明: 本文由大熊科技原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权