Java社招面试题:如何在两个线程间共享数据?

104 阅读3分钟



哈喽,大家好,我是小米,一个喜欢分享技术的小伙伴!今天咱们来聊聊一个面试中常见但又容易被问懵的问题——如何在两个线程间共享数据。别急,先泡杯咖啡,听我用故事把这个问题讲清楚~

面试场景复盘:张三的“共享”迷惑

话说,有一天,咱们的主角张三去面试,面试官微微一笑:“张三啊,如果有两个线程需要共享一个变量,你会怎么实现?”

张三脑袋一热,先甩了个“用synchronized”,然后又补了句“volatile也行”。

面试官笑着点了点头:“嗯,那再深入一点,你觉得它们什么时候适合用?”

这下,张三慌了……

什么是线程间数据共享?

线程间共享数据,顾名思义,就是两个或多个线程可以同时访问或修改同一块数据。比如我们生活中的外卖订单系统:

  • 用户下单 -> 系统创建订单(线程A)。
  • 骑手接单 -> 系统更新订单状态为“配送中”(线程B)。

问题在于:如何保证线程A和线程B对同一订单的数据操作不会冲突?

用共享对象作为桥梁

故事情节:共享日记本

假如两个朋友小红和小明想通过写日记交流,每个人都可以往同一本日记本里写内容,但他们得约定:

  • 一次只能有一个人动笔(线程同步)。
  • 避免互相覆盖(数据一致性)。

用代码表示,我们可以用一个共享对象(比如Order类)来保存数据:

然后两个线程操作这个共享对象:

借助volatile实现轻量级共享

故事情节:实时天气广播

小红和小明在家看电视,电视播报当前的天气情况:

  • 天气信息每秒更新一次(线程A)。
  • 小红和小明随时可能抬头看看天气(线程B)。

在这种场景下,volatile可以用来保证共享变量的可见性

线程操作:

注意: volatile只保证可见性,不保证操作的原子性,比如currentWeather++这种操作,仍需要synchronized或AtomicInteger来保护。

用Lock实现高级控制

故事情节:抢占篮球场

假如学校有一个篮球场,小红和小明需要使用它:

  • 谁先抢到球,谁先用(公平性)。
  • 用完后要交出来(释放资源)。

在Java中,Lock可以提供更灵活的控制:

两个线程操作:

面试官的“灵魂拷问”

1. volatile和synchronized区别是什么?

  • volatile适用于简单的状态标记或变量更新;
  • synchronized适合更复杂的线程同步逻辑,比如多个操作的原子性要求。

2. Lock相比synchronized有啥优势?

  • 更灵活:可以尝试加锁或设置超时;
  • 支持条件变量(Condition)实现更复杂的线程协调。

3. 数据共享的场景该如何选择?

  • 简单标记更新:volatile。
  • 单线程独占操作:synchronized或Lock。
  • 更高并发需求:Lock或Atomic类。

总结与彩蛋

回到张三的面试题,你会怎么回答?以下是一个参考答案:

在两个线程间共享数据,常见的方式包括:

  • 使用volatile保证变量的可见性;
  • 使用synchronized或Lock保证原子性和互斥访问;
  • 如果数据量较大,也可以使用线程安全的集合类,比如ConcurrentHashMap。

最后,别忘了告诉面试官:具体实现要看场景需求哦!

END

好了,今天的分享就到这里,希望大家喜欢!有什么问题可以留言讨论,小米随时在线~

点赞+在看,冲鸭!

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!