说说你了解的线程同步方式

Java线程同步主要通过以下几种机制实现,确保多线程环境下共享资源的安全访问:

1.synchronized关键字

原理

  • 基于JVM内置锁(监视器锁),通过修饰方法或代码块实现互斥访问。

  • 线程进入同步代码前自动获取锁,退出时自动释放锁(包括异常退出)

  • 提供互斥锁,确保同一时间只有一个线程访问同步代码块或方法。

// 同步实例方法:锁对象为当前实例。
public synchronized void syncMethod() {
    // 临界区代码
}
​
// 同步代码块:显式指定锁对象(任意对象)
public void syncBlock() {
    synchronized (lockObject) {
        // 临界区代码
    }
}
​
//同步静态方法:锁对象为类的Class对象。
public static synchronized void staticMethod() {
    // 同步代码
}
  • 特点:

    • 隐式加锁/解锁,代码简洁。

    • JDK 1.6 后优化了锁机制(偏向锁、轻量级锁、重量级锁),性能提升显著。

    • 不可中断,无法设置超时。

2. ReentrantLock(显式锁)

原理

  • 实现Lock接口,提供更灵活的锁控制(可重入、公平/非公平锁)。

  • 需手动调用lock()unlock(),支持超时锁、可中断锁

private final ReentrantLock lock = new ReentrantLock();
​
public void performTask() {
    lock.lock();  // 手动加锁
    try {
        // 临界区代码
    } finally {
        lock.unlock();  // 必须在finally中释放
    }
}
​
// 尝试获取锁(超时机制)
if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try { /* 操作 */ } finally { lock.unlock(); }
} else {
    // 备选逻辑
}

适用场景

  • 需精细控制锁(如公平锁、超时锁)。

  • 复杂同步逻辑(如多条件变量Condition实现生产者-消费者模型)

  • 特点:

    • 支持可中断锁(lockInterruptibly())、超时锁(tryLock(timeout))、公平锁。

    • 需手动加锁/解锁,避免死锁。

    • 适合高竞争或复杂同步场景。

3. 原子变量(Atomic类)

原理

  • 基于CAS(Compare and Swap)操作,通过硬件指令保证原子性(无锁同步)。

  • 适用于简单变量(如AtomicIntegerAtomicReference)。

private AtomicInteger counter = new AtomicInteger(0);
​
public void increment() {
    counter.incrementAndGet();  // 原子自增
}

适用场景

  • 高并发场景下的计数器、状态标志。

  • 替代synchronized提升性能(如累加操作)

  • 性能优于锁,但仅支持单一变量。

4. 线程安全的并发集合

原理

  • 内部实现线程安全机制,无需额外同步

  • 例如:

    • ConcurrentHashMap:分段锁/CAS + 红黑树(JDK8+)。

    • CopyOnWriteArrayList:写时复制,适合读多写少。

    • BlockingQueue(如ArrayBlockingQueue):基于锁的阻塞队列

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key", 1);  // 线程安全操作
​
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item");  // 写操作复制新数组

适用场景

  • 高并发数据存储(如缓存、任务队列)。

  • 读多写少(CopyOnWriteArrayList)或读写均衡(ConcurrentHashMap

5. 其他同步工具

信号量(Semaphore
  • 控制资源访问的并发数(如数据库连接池)

Semaphore semaphore = new Semaphore(10); // 允许10个线程并发
semaphore.acquire();  // 获取许可
try { /* 操作 */ } finally { semaphore.release(); }
倒计时门闩(CountDownLatch
  • 等待多个线程完成后再执行主线程(如批量任务汇总)

CountDownLatch latch = new CountDownLatch(5);
// 子线程完成任务后调用 latch.countDown()
latch.await();  // 主线程等待所有任务完成
线程局部变量(ThreadLocal
  • 每个线程持有变量的独立副本,避免共享(如数据库连接)

private static ThreadLocal<Connection> connHolder = ThreadLocal.withInitial(() -> getConnection());

总结:如何选择同步方式?

同步方式优势适用场景
synchronized自动锁释放,语法简单简单同步逻辑,低竞争场景
ReentrantLock支持超时、可中断锁,公平性可控高竞争复杂逻辑(如死锁处理)
原子变量无锁操作,高性能计数器、状态标志
并发集合内置线程安全,无需额外同步共享数据存储(缓存、队列)
Semaphore/Latch控制并发数或协调多线程资源池、批量任务调度

实践建议

  • 优先使用并发集合(如ConcurrentHashMap)减少手动同步;

  • 简单操作选原子变量,复杂逻辑用ReentrantLock

  • 避免滥用synchronized修饰整个方法,缩小同步范围

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tsxchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值