多线程基本概念

  • 什么是进程,线程?

线程是进程的最小执行单元,相当于不同的执行路径

  • run和start的区别?

run只是单纯的方法调用,在主线程进行.start相当于开启一个线程

  • 线程的启动的三种方式

Thread,runable,线程池

  • 线程的6个状态

  • 可重入锁和不可重入的区别

可重入锁也叫递归锁,是在一个线程获取锁后,内部如果还需要获取锁,可以直接获取的锁(前提锁对象得是同一个对象或者class)。
不可重入锁也就是相反,线程获取锁后,内部不能再获取锁,由于之前已经获取过还没释放而阻塞,会导致线程死锁。
所以可重入锁的一个优点是可一定程度避免死锁。
可重入锁有ReentrantLock和synchronized。
非可重入锁有NonReentrantLock

  • 出现异常,锁会释放吗?

  • 锁升级的过程?

第一次:markword 记录这个线程id(偏向锁)
如果线程争用:升级为自旋锁
10次以后,升级为重量级锁 - OS

锁只能升级,不能降级

  • 什么时候用自旋锁,什么时候用系统锁?

自旋锁占cpu,但不访问操作系统,在用户态解决锁的问题,不经过内核态.
加锁代码执行时间短,且线程数少用自旋锁.执行时间长或线程数多用系统锁.不然cpu受不了

  • synchronized可以锁定String常量,Integer,Long吗?

不能,会存在问题 synchronized ("A".intern()),
串池大小依赖服务器内存,且只有等待fullGC,极端情况下会导致频繁fullGC。并且在数据量很大的情况下,将字符串放入常量是存在性能问题。

  • volitile的两个作用?

1.保持可见性(缓存一致性协议)
2.禁止指令重排序

public class Instance {
    private static volatile Instance instance;

    static Instance getInstance(){
        if(instance == null){
            synchronized (Instance.class){
                if(instance == null){
                    return new Instance();
                }
            }
        }
        return instance;
    }
}
  • 为什么volatile不能保证多个线程共同修改某个变量带来的不一致问题

线程1改了值,线程 2,3同时读到了这个值,count++不具备原子性

  • 用于加锁的对象要记得加final,防止被修改

  • 什么是CAS?

无锁优化,自旋.Compare And Set
cas(V,Expected,NewValue)
- if V == E
V = New
otherwise try again or fail
- CPU原语支持 所以不用担心 第一二步之间被其他线程抢先

  • JUC 常用锁

CountDownLatch,CyclicBarrier,Phaser,ReadWriteLock,Semaphore,Exchanger,LockSupport

  • wait,notify生产者消费者代码
public class MyContainer<T> {

    final private LinkedList<T> lists = new LinkedList<>();
    final private int Max = 10;

    public synchronized void put (T t){
        while(lists.size() == Max){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        lists.add(t);
        this.notifyAll(); //通知消费者进行消费
    }

    public synchronized T get (){
        T t = null;
        while(lists.size() == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        t = lists.removeFirst();
        this.notifyAll();
        return t;
    }
    
    public static void main(String[] args) {
        MyContainer<String> c = new MyContainer<>();
        for (int i = 0; i < 10; i++) {
            new Thread(() ->{
                for(int j =0;j<5; j++) System.out.println(c.get());
            },"c"+i).start();
        }
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        //生产者线程
        for (int i = 0; i < 2; i++) {
            new Thread(() ->{
                for(int j =0;j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
            },"p"+i).start();
        }
    }
}
  • ReentrantLock的Condition的本质是什么?

不同的等待队列,new Condition就多创建一个等待队列

posted @   Acaak  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示