原创

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机制通过全量复制数组的方式来实现,并包括CopyOnWriteArrayListCopyOnWriteArraySet等。这种机制适用于写操作较少的场景,但需要注意可能带来的内存消耗。

示例:使用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"开头的并发工具类,例如ConcurrentHashMapConcurrentLinkedDequeConcurrentLinkedQueue等。它们提供了更多复杂场景下的解决方案。

本教程深入讨论了Java中的无锁技术,包括原子工具类、线程本地存储、Copy-On-Write等,并通过实例演示了它们的使用。了解这些技术,可以更好地处理并发编程中的各种挑战,提高程序的性能和稳定性。

正文到此结束
本文目录