保定网站制作网站网站建设方案图
2026/1/7 10:42:23 网站建设 项目流程
保定网站制作网站,网站建设方案图,会员管理系统app免费版,学ui设计需要要哪方面基础文章目录当线程占用了synchronized方法锁#xff0c;其它线程是否能挤进同一对象的其它方法#xff1f;一、问题背景#xff1a;线程间的“争抢”游戏二、初步理解#xff1a;锁到底锁住了什么#xff1f;三、深入探讨#xff1a;锁的粒度与类型1. 对象级别的锁2. 类级别…文章目录当线程占用了synchronized方法锁其它线程是否能挤进同一对象的其它方法一、问题背景线程间的“争抢”游戏二、初步理解锁到底锁住了什么三、深入探讨锁的粒度与类型1. 对象级别的锁2. 类级别的锁3. 显式锁四、案例分析如何让多个线程并发访问1. 使用显式锁2. 使用synchronized块3. 使用无锁编程五、总结这些方法可以有效地提高系统的并发性能同时确保数据的一致性和安全性。 领取 | 1000 套高质量面试题大合集无套路闫工带你飞一把当线程占用了synchronized方法锁其它线程是否能挤进同一对象的其它方法大家好我是闫工今天我们要聊一个关于Java多线程编程的有趣话题当一个线程占用了synchronized方法锁时其他线程能不能挤进同一个对象的其他方法呢这个问题听起来有点抽象但其实非常贴近我们的日常开发。让我用一种轻松幽默的方式带大家一步步解开这个谜团。一、问题背景线程间的“争抢”游戏在Java中synchronized关键字是一个非常强大的工具它可以帮助我们控制多个线程对共享资源的访问从而避免并发带来的各种问题比如数据不一致、竞态条件等等。但是有时候我们会遇到一些看似简单但又容易让人困惑的问题。假设我们有一个对象比如说一个银行账户类publicclassBankAccount{privatedoublebalance;publicsynchronizedvoiddeposit(doubleamount){// 存钱操作balanceamount;}publicsynchronizedvoidwithdraw(doubleamount){// 取钱操作if(balanceamount){balance-amount;}}}在这个例子中deposit和withdraw方法都使用了synchronized关键字。现在假设线程A正在执行deposit方法那么线程B能不能同时进入withdraw方法呢这个问题涉及到Java的锁机制我们需要深入探讨一下。二、初步理解锁到底锁住了什么在Java中synchronized方法会自动获取对象的锁也称为监视器锁。这个锁是与特定对象相关的。也就是说当一个线程进入某个对象的一个synchronized方法时它就占用了该对象的锁其他线程必须等待直到锁被释放。所以在上面的例子中如果线程A正在执行deposit方法那么线程B在尝试调用withdraw方法时会被阻塞直到线程A完成并释放了锁。这就是为什么其他线程不能同时进入同一个对象的其他synchronized方法的原因。但是这似乎有些“霸道”因为两个方法可能并不互相干扰比如存款和取款操作可能是独立的。那么是否有一种方式可以让它们并发执行呢答案是肯定的但需要使用更细粒度的锁机制比如ReentrantLock或者synchronized块。三、深入探讨锁的粒度与类型在Java中锁有不同的粒度和类型这会影响线程的行为。最常见的是对象级别的锁这是默认的synchronized方法所使用的锁它锁定了整个对象。类级别的锁使用synchronized static方法时锁的是类本身。显式锁通过ReentrantLock等锁实现可以更灵活地控制锁的粒度和范围。1. 对象级别的锁让我们回到之前的例子。如果两个线程分别调用同一个对象的两个synchronized方法那么它们会被串行执行因为这两个方法共享同一个对象锁。这种情况下无论方法的内容如何都只能一个接一个地执行。这可能会导致性能问题特别是当这些方法之间没有直接依赖关系时。比如在银行账户的例子中存款和取款操作可能彼此独立但仍然需要排队等待对方完成。这显然不是最优的解决方案。2. 类级别的锁有时候我们需要锁住整个类而不是某个实例。例如publicclassSingleton{privatestaticvolatileSingletoninstance;publicsynchronizedstaticSingletongetInstance(){if(instancenull){instancenewSingleton();}returninstance;}}在这个例子中getInstance方法是静态的并且使用了synchronized关键字。这意味着所有调用这个方法的线程都会竞争同一个类锁而不是实例锁。这在单例模式中非常有用因为它确保了无论有多少个线程调用getInstance()都只会创建一个实例。3. 显式锁为了更灵活地控制锁的行为Java提供了ReentrantLock等显式锁机制。与synchronized不同ReentrantLock需要手动获取和释放锁并且支持尝试获取锁、中断获取锁等功能。这在处理复杂的并发场景时非常有用。举个例子publicclassBankAccount{privatedoublebalance;privatefinalReentrantLocklocknewReentrantLock();publicvoiddeposit(doubleamount){lock.lock();try{// 存钱操作balanceamount;}finally{lock.unlock();}}publicvoidwithdraw(doubleamount){lock.lock();try{if(balanceamount){balance-amount;}}finally{lock.unlock();}}}在这个例子中deposit和withdraw方法都使用了同一个ReentrantLock实例。这意味着它们仍然会被串行执行除非我们使用不同的锁策略。不过通过显式锁我们可以更灵活地控制锁的粒度。四、案例分析如何让多个线程并发访问现在我们回到最初的问题当一个线程占用了synchronized方法锁时其他线程能不能进入同一个对象的其他方法答案是不能。但是我们可以采取一些措施来缓解这个问题。1. 使用显式锁如前所述使用显式锁比如ReentrantLock可以让我们更灵活地控制锁的行为。例如我们可以为每个方法分配不同的锁publicclassBankAccount{privatedoublebalance;privatefinalReentrantLockdepositLocknewReentrantLock();privatefinalReentrantLockwithdrawLocknewReentrantLock();publicvoiddeposit(doubleamount){depositLock.lock();try{// 存钱操作balanceamount;}finally{depositLock.unlock();}}publicvoidwithdraw(doubleamount){withdrawLock.lock();try{if(balanceamount){balance-amount;}}finally{withdrawLock.unlock();}}}在这个例子中deposit和withdraw方法分别使用了不同的锁。这意味着它们可以并发执行只要各自的锁没有被占用。2. 使用synchronized块另外一种方式是使用synchronized块并且为每个方法指定不同的同步对象。例如publicclassBankAccount{privatedoublebalance;privatefinalObjectdepositMutexnewObject();privatefinalObjectwithdrawMutexnewObject();publicvoiddeposit(doubleamount){synchronized(depositMutex){// 存钱操作balanceamount;}}publicvoidwithdraw(doubleamount){synchronized(withdrawMutex){if(balanceamount){balance-amount;}}}}在这个例子中deposit和withdraw方法分别同步了不同的对象depositMutex和withdrawMutex因此它们可以并发执行。3. 使用无锁编程在某些情况下我们可以使用无锁编程技术来避免显式的锁竞争。例如使用原子变量importjava.util.concurrent.atomic.AtomicDouble;publicclassBankAccount{privateAtomicDoublebalancenewAtomicDouble(0);publicvoiddeposit(doubleamount){while(true){doublecurrentBalancebalance.get();if(balance.compareAndSet(currentBalance,currentBalanceamount)){break;}}}publicvoidwithdraw(doubleamount){while(true){doublecurrentBalancebalance.get();if(currentBalanceamountbalance.compareAndSet(currentBalance,currentBalance-amount)){break;}}}}在这个例子中deposit和withdraw方法使用了AtomicDouble类并且通过compareAndSet方法来进行无锁的更新操作。这意味着它们可以并发执行而不会互相阻塞。五、总结当一个线程占用了synchronized方法锁时其他线程无法进入同一个对象的其他synchronized方法因为这些方法共享同一个对象锁。因此如果我们需要让多个线程并发访问不同的部分代码我们需要采取以下措施使用显式锁通过ReentrantLock等显式锁机制我们可以为不同的方法分配不同的锁。使用synchronized块在synchronized块中指定不同的同步对象。使用无锁编程利用原子变量和无锁数据结构来避免显式的锁竞争。这些方法可以有效地提高系统的并发性能同时确保数据的一致性和安全性。 领取 | 1000 套高质量面试题大合集无套路闫工带你飞一把成体系的面试题无论你是大佬还是小白都需要一套JAVA体系的面试题我已经上岸了你也想上岸吗闫工精心准备了程序准备面试想系统提升技术实力闫工精心整理了1000 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 详细解析并附赠高频考点总结、简历模板、面经合集等实用资料✅ 覆盖大厂高频题型✅ 按知识点分类查漏补缺超方便✅ 持续更新助你拿下心仪 Offer免费领取 点击这里获取资料已帮助数千位开发者成功上岸下一个就是你✨

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询