接近一个半小时,第一面问的东西都比较基础,偏向于操作系统、网络、数据库等方面。没有问语言相关的东西,没有怎么涉及微服务和分布式的内容。总体对我来说也比较简单。截至目前(2022年03月06日)没有通知下一面。

操作系统

主线程和子线程之间什么内容是共享的,什么内容是不共享的?主线程和子线程如果要修改同一个变量,应该怎么做(线程安全)?

首先讨论第一个问题,关于内容共享。

此处表面上是讨论主线程和子线程之间的关系,其实深层次在讨论内存模型。这里用JVM举例(因为我也不知道其他语言或者系统的内存模型是怎么样的,迟点研究一下)

jvm内存模型概述

JVM内存模型(通俗易懂)_抵制平庸 拥抱变化的博客-CSDN博客_jvm内存模型

Untitled

Untitled

简而言之,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());
}

那么正好就引出了第二个问题,两个线程如何修改同一个数据?线程不安全的例子就像上面,随便改。但是我理解这里需要考虑线程安全的问题。

Java 并发 | CS-Notes

有很多种方式保证线程安全的修改,例如:

进程间的通信方式?(IPC方式)

向上走一级到进程。进程间的通信方式。进程方式有很多种,但是无非离不开:管道、共享内存、套接字、信号量这些基础概念。