news 2026/9/19 13:07:03

java开发中常见锁的使用场景和代码示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java开发中常见锁的使用场景和代码示例

文章快速指引

    • 一、java中锁的作用
    • 二、synchronized
    • 三、ReentrantLock
    • 三、ReadWriteLock
    • 四、Condition
    • 五、StampedLock
    • 六、LockSupport
    • 七、CountDownLatch

一、java中锁的作用

在Java中,锁(Locks)是一种同步机制,主要用于控制多线程环境下的资源访问,确保数据的一致性和线程安全。锁的主要作用可以概括为以下几个方面:

  1. 互斥访问
    锁能够防止多个线程同时访问共享资源,确保任何时刻只有一个线程能够进入临界区,从而避免数据竞争和不一致状态。
  2. 原子操作保证
    通过锁,可以确保某些关键操作(如修改共享变量)在执行时不会被其他线程中断,保证了这些操作的原子性。
  3. 线程同步
    锁可以用于实现线程间的同步,例如一个线程等待另一个线程完成某个任务后继续执行,这有助于协调多线程程序中的复杂流程。
  4. 避免死锁和活锁
    虽然锁本身可能导致死锁和活锁问题,但合理使用锁机制可以避免这些问题的发生,确保程序的稳定运行。
  5. 提高并发性能
    虽然锁会带来一定的性能开销,但在适当的地方使用锁可以提高并发性能,尤其是在多处理器系统中,合理的锁策略能够有效利用硬件资源。
  6. 读写锁优化
    Java提供了读写锁(ReentrantReadWriteLock),允许多个读取线程同时访问共享资源,但写入操作是排他的。这种机制在读操作远多于写操作的场景下,可以显著提升并发性能。
  7. 公平性和非公平性
    Java中的锁还可以设置为公平锁或非公平锁,公平锁按照线程请求锁的顺序分配锁,而非公平锁则可能让后来的线程先获得锁,提高了锁的获取速度,但牺牲了一定的公平性。

二、synchronized

  1. 使用场景
    在简单的多线程环境中,当需要确保一个共享资源在同一时间只能被一个线程访问时,synchronized关键字非常有用。例如,用于同步对全局变量的访问,或是在银行账户转账、票务系统中确保事务的一致性。

  2. 代码示例

    publicclassSynchronizedExample{privateintcount=0;privateObjectlock=newObject();publicvoidincrement(){synchronized(lock){count++;}}}

三、ReentrantLock

  1. 使用场景
    当需要更灵活的锁控制时,比如可中断的锁、公平锁或是需要在锁上附加额外行为时,ReentrantLock是更好的选择。例如,在实现一个线程池或管理一个线程安全的队列时,使用ReentrantLock可以更好地控制锁的行为。

  2. 代码示例

    importjava.util.concurrent.locks.ReentrantLock;publicclassReentrantLockExample{privateintcount=0;privateReentrantLocklock=newReentrantLock();publicvoidincrement(){lock.lock();try{count++;}finally{lock.unlock();}}}

三、ReadWriteLock

  1. 使用场景
    读写锁适用于读多写少的并发场景:大量线程高频读取共享数据,修改操作频次很低,利用读锁共享、写锁互斥的特性,在读操作之间不互相阻塞,以此提高系统的并发吞吐量,写操作时独占锁保证数据一致性。

  2. 代码示例

    importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.locks.ReadWriteLock;importjava.util.concurrent.locks.ReentrantReadWriteLock;publicclassSafeCache{privatefinalMap<String,Object>cache=newHashMap<>();privatefinalReadWriteLockrwLock=newReentrantReadWriteLock();// 读操作:多个线程可以并发读取publicObjectget(Stringkey){rwLock.readLock().lock();try{returncache.get(key);}finally{rwLock.readLock().unlock();}}// 写操作:独占访问,保证数据一致性publicvoidput(Stringkey,Objectvalue){rwLock.writeLock().lock();try{cache.put(key,value);}finally{rwLock.writeLock().unlock();}}// 删除操作publicvoidremove(Stringkey){rwLock.writeLock().lock();try{cache.remove(key);}finally{rwLock.writeLock().unlock();}}}

四、Condition

  1. 使用场景
    Condition接口常与ReentrantLock搭配使用,用于更精细的线程间通信,如生产者-消费者模型中,生产者和消费者线程可以基于不同的条件进行等待和唤醒,而不需要整个锁的范围被阻塞。

  2. 代码示例

    importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.ReentrantLock;publicclassConditionExample{privateintcount=0;privateReentrantLocklock=newReentrantLock();privateConditioncondition=lock.newCondition();publicvoidincrement(){lock.lock();try{count++;condition.signalAll();}finally{lock.unlock();}}publicvoidawait()throwsInterruptedException{lock.lock();try{while(count==0){condition.await();}// 执行其他操作}finally{lock.unlock();}}}

五、StampedLock

  1. 使用场景
    在读操作远远多于写操作的场景中,StampedLock提供了一种高性能的读写锁机制。例如,在数据库查询结果缓存中,大多数操作都是读取,偶尔才会有写入,此时使用StampedLock可以显著提高读取性能。

  2. 代码示例

    importjava.util.concurrent.locks.StampedLock;publicclassStampedLockExample{privateintx=0;privateinty=0;privateStampedLocklock=newStampedLock();publicvoidwriteData(intnewX,intnewY){longstamp=lock.writeLock();try{x=newX;y=newY;}finally{lock.unlockWrite(stamp);}}publicdoublereadDistanceFromOrigin(){longstamp=lock.tryOptimisticRead();intcurrentX=x;intcurrentY=y;if(!lock.validate(stamp)){stamp=lock.readLock();try{currentX=x;currentY=y;}finally{lock.unlockRead(stamp);}}returnMath.sqrt(currentX*currentX+currentY*currentY);}}

六、LockSupport

  1. 使用场景
    LockSupport主要用于实现自定义的同步器或更底层的线程同步机制。例如,在设计自定义的信号量或实现更复杂的线程调度算法时,LockSupport提供了必要的原语支持。
  2. 代码示例
    importjava.util.concurrent.locks.LockSupport;publicclassLockSupportExample{publicvoiddoSomething(){// 执行前置操作LockSupport.park();// 阻塞当前线程// 执行后置操作}publicvoidwakeupThread(){// 唤醒阻塞的线程LockSupport.unpark(thread);}}

七、CountDownLatch

  1. 使用场景
    当一个线程需要等待若干个子线程全部完成某个任务后才能继续执行时,CountDownLatch非常合适。例如,在分布式系统中,主节点可能需要等待所有子节点完成数据处理后才能汇总结果。

  2. 代码示例

    importjava.util.concurrent.CountDownLatch;publicclassCountDownLatchExample{privateCountDownLatchlatch=newCountDownLatch(3);publicvoiddoSomething()throwsInterruptedException{// 执行前置操作latch.countDown();// 完成任务,计数器减1latch.await();// 等待其他线程完成任务// 执行后置操作}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 13:04:02

Hadoop与Hive构建足球数据仓库:从事件表到预测分析

简介&#xff1a;这份《hadoop大数据课件-足球大数据案例》面向大数据初学者、足球数据分析爱好者及体育科技从业者&#xff0c;以足球赛事场景演示Hadoop在体育数据挖掘中的典型应用。课件围绕“足球的大数据7种武器”展开&#xff0c;覆盖比赛统计、热点图与轨迹图、球员统计…

作者头像 李华
网站建设 2026/9/19 13:03:34

语音AI智能体落地路径:从三十秒演示到全天候语音客服系统

语音AI智能体落地路径&#xff1a;从三十秒演示到全天候语音客服系统 【免费下载链接】awesome-llm-apps 100 AI Agents, Agent Skills and RAG Apps - Free and Open Source. 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-llm-apps 你在做语音AI智能体—…

作者头像 李华
网站建设 2026/9/19 13:03:30

React Native鸿蒙移动端数据筛选性能优化实战

1. 项目背景与需求解析在移动端采购管理系统中&#xff0c;数据筛选功能是高频使用的核心模块。传统方案往往采用全量查询后端过滤的模式&#xff0c;这在数据量较大时会导致明显的性能瓶颈。我们团队最近在重构某大型零售企业的采购APP时&#xff0c;就遇到了这个典型问题——…

作者头像 李华