多线程 问答
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实现阻塞队列,(生产者,消费者)
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
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
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
备注:公众号清汤袭人能找到我,那是随笔的地方