接近一个半小时,第一面问的东西都比较基础,偏向于操作系统、网络、数据库等方面。没有问语言相关的东西,没有怎么涉及微服务和分布式的内容。总体对我来说也比较简单。截至目前(2022年03月06日)没有通知下一面。
首先讨论第一个问题,关于内容共享。
此处表面上是讨论主线程和子线程之间的关系,其实深层次在讨论内存模型。这里用JVM举例(因为我也不知道其他语言或者系统的内存模型是怎么样的,迟点研究一下)
JVM内存模型(通俗易懂)_抵制平庸 拥抱变化的博客-CSDN博客_jvm内存模型
简而言之,JVM中只有一个堆,但是对于每一个线程,有自己的程序计数器、JVM(虚拟机)栈、本地方法栈。
创建的对象存储在堆中,所以存在以下的方法对方法进行引用。这时候可以认为对象是被线程共享的。
// 线程不安全,对ThreadUnsafeExample进行修改,示例来自:<http://www.cyc2018.xyz/Java/Java%20%E5%B9%B6%E5%8F%91.html#%E4%B9%9D%E3%80%81%E7%BA%BF%E7%A8%8B%E4%B8%8D%E5%AE%89%E5%85%A8%E7%A4%BA%E4%BE%8B>
public static void main(String[] args) throws InterruptedException {
final int threadSize = 1000;
ThreadUnsafeExample example = new ThreadUnsafeExample();
final CountDownLatch countDownLatch = new CountDownLatch(threadSize);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < threadSize; i++) {
executorService.execute(() -> {
example.add();
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println(example.get());
}
那么正好就引出了第二个问题,两个线程如何修改同一个数据?线程不安全的例子就像上面,随便改。但是我理解这里需要考虑线程安全的问题。
有很多种方式保证线程安全的修改,例如:
向上走一级到进程。进程间的通信方式。进程方式有很多种,但是无非离不开:管道、共享内存、套接字、信号量这些基础概念。