多线程 问答
1、线程的状态或什么周期
新建,就绪,运行,阻塞,销毁
new, runnable,running,blocked,terminated
java角度
2、java里面,wait和 sleep的区别
wait 是object的方法,等待时会释放锁
sleep是 线程Thread的方法,睡眠时不会释放持有的对象锁,需要捕获异常。结束睡眠后,进入 runnable状态。如果线程异常终止,terminated状态
object的 wait,notify,notifyall 用于同步控制
sleep可以在任何地方用
3、进程和线程的区别
进程是最小的资源分配单位,线程是最小的执行单位
4、程序开多少线程合适
2n+1
5、synchronized 和 lock的区别
简述一下sync从偏向锁 升级到到轻量锁的情况
前提:在偏向锁和轻量锁开启的情况下,当线程进入时,首先会加上偏量锁
1、判断是否可偏向的状态:markWord锁标志为 01,是否偏向锁为 1
2、当可偏向,查看线程ID 如果是自己,则执行代码(第5步);否则执行第3步
3、cas竞争锁,如果成功,则记录markword里面的线程ID为自己,执行代码(第5步);否则执行第4步
4、如果cas失败表示有竞争,达到savepoint时,偏向锁线程挂起,升级为轻量锁。 被阻塞在安全点的额线程继续往下执行同步代码???
5、执行代码
6、DCL double check?
if singleton == null
synchronized(singleton.class){
if singleton == null{singleton=new singleton();}
}
7、condition实现阻塞队列,(生产者,消费者)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ProviderConsumer<T> { private int length; private Queue<T> queue; private ReentrantLock lock= new ReentrantLock(); Condition providerCondition =lock.newCondition(); Condition consumerCondition =lock.newCondition(); private ProviderConsumer( int length){ this .length=length; queue= new LinkedList<T>(); } private void add(T product){ lock.lock(); try { while (queue.size()>=length) { providerCondition.await(); } queue.add(product); consumerCondition.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } private T consume(){ lock.lock(); try { while (queue.isEmpty()) { consumerCondition.await(); } T product=queue.remove(); providerCondition.signal(); return product; } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } return null ; } } |
=
8、按顺序打印abc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class PrintABC { ReentrantLock lock= new ReentrantLock(); Condition conditionA= lock.newCondition(); Condition conditionB= lock.newCondition(); Condition conditionC= lock.newCondition(); int value= 0 ; //打印几遍 int count; private PrintABC( int count){ this .count=count; } private void printabc(){ new Thread( new ThreadC()).start(); new Thread( new ThreadB()).start(); new Thread( new ThreadA()).start(); } public static void main(String[] args) { PrintABC abc= new PrintABC( 2 ); abc.printabc(); } class ThreadA implements Runnable{ @Override public void run() { lock.lock(); try { for ( int i = 0 ; i < count; i++) { while (value% 3 != 0 ){ conditionA.await(); } System.out.println( "A" ); value++; conditionB.signal(); } } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } } class ThreadB implements Runnable{ @Override public void run() { lock.lock(); try { for ( int i = 0 ; i < count; i++) { while (value% 3 != 1 ){ conditionB.await(); } System.out.println( "B" ); value++; conditionC.signal(); } } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } } class ThreadC implements Runnable{ @Override public void run() { lock.lock(); try { for ( int i = 0 ; i < count; i++) { while (value% 3 != 2 ){ conditionC.await(); } System.out.println( "C" ); value++; conditionA.signal(); } } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } } } |
9、volatile 的作用和怎么实现的
可见性,防止指令重排序
volatile修饰的变量,修改后可以立即同步到内存;使用前也会从内存刷新。本质上也是通过内存屏障 实现的
store store
volatile 写
store load
load load
volatile 读
load store
9、concurrentHashMap
1.7 是分段锁
1.8 舍弃了分段锁,每次锁住的是 node对象,而不是某一段数组。元素存在Node数组中
我根据原代码
java.util.HashMap#putVal
java.util.concurrent.ConcurrentHashMap#putVal
1 2 3 4 5 6 | else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); else { V oldVal = null ; synchronized (f) { if (tabAt(tab, i) == f) { |
10、三个线程,按顺序执行,
join??
join属于强行插队,例如在主线程中,如果子线程.join,让主线程就会让出cpu给子线程
join里面的实现方法,用的是wait,会释放锁。
11、
=
参考地址:
https://blog.csdn.net/Firstlucky77/article/details/125173318
备注:公众号清汤袭人能找到我,那是随笔的地方
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)