小米最近在参加社招面试,我是一名经验丰富的Java开发工程师,但在一次面试中,面试官抛出一个问题:“线程同步和线程互斥有什么区别?有哪些实现方式?”
面对这个问题,小米决定好好整理一番,分享给大家,帮助更多小伙伴掌握多线程编程的核心知识!
线程同步和线程互斥的区别
在Java多线程编程中,我们常常需要处理多个线程访问共享资源的问题。为了解决这个问题,我们会使用线程同步和线程互斥的机制。
- 线程同步(Synchronization):保证多个线程按照有序的方式访问共享资源,避免数据不一致的情况。例如,多个线程往同一个文件写入数据时,需要按照一定顺序进行,否则内容可能会错乱。
- 线程互斥(Mutex):保证同一时刻只能有一个线程访问共享资源,防止多个线程同时修改导致数据混乱。例如,多个线程对一个账户进行扣款操作,如果不加互斥,可能导致账户余额异常。
简单理解:
- 同步是让多个线程按照一定规则执行,不会打架。
- 互斥是让多个线程排队,一个一个来,防止争抢资源。
synchronized 关键字
synchronized 是Java提供的最简单的同步机制,它可以用来修饰方法或代码块,确保同一时间只有一个线程可以访问。
示例:同步方法
解析:
- synchronized 关键字加在 withdraw 方法上,保证同一时刻只有一个线程能执行取款操作,避免数据不一致的问题。
示例:同步代码块
解析:
- synchronized (this) 只锁定 withdraw 方法中的代码块,而不是整个方法,提高并发效率。
Lock(显式锁)
synchronized 是隐式锁,但 Java 还提供了 Lock 机制,它可以手动加锁和释放锁,提供更多的控制能力。
示例:使用 ReentrantLock
解析:
- lock.lock() 申请锁,lock.unlock() 释放锁,避免 synchronized 的局限性。
- finally 代码块确保锁能释放,即使发生异常。
ReadWriteLock(读写锁)
如果有多个线程读取共享资源,但只有少数线程修改资源,可以使用读写锁来提高性能。
示例:使用 ReadWriteLock
解析:
- readLock() 允许多个线程同时读取,提高并发能力。
- writeLock() 只有一个线程能写,防止数据不一致。
Semaphore(信号量)
Semaphore 允许多个线程同时访问共享资源,但限制最大并发数。
示例:限制最多2个线程访问
解析:
- semaphore.acquire() 获取许可证,如果没有空位,则等待。
- semaphore.release() 释放许可证,让其他线程可以访问。
Atomic 变量
如果只是对单个变量进行同步(如计数器递增),可以使用 AtomicInteger,比 synchronized 更高效。
示例:AtomicInteger
解析:
- count.incrementAndGet() 是原子操作,不会被其他线程打断。
总结
小米面试完后,面试官笑了:“不错,思路清晰,掌握了多种同步方式!”
END
希望这篇文章能帮助到正在准备Java面试的小伙伴们,加油!
如果你觉得有用,欢迎点赞、收藏、转发,让更多人受益!
我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
本文暂时没有评论,来添加一个吧(●'◡'●)