多线程的相关知识点
CAS compare and swap 比较和交换
先把值读过来,,然后回写的时候判断,值有没有动过,如果值被改动过,在把值重新读取过来,,然后操作后在回写(回写的时候需要判断),
ABA 问题 加版本号。
底层实现:最终调用native 方法 compareAndSwapInt
汇编级别 lock cmpxchg,lock指令其他cpu不许打断,锁定了一个北桥信号。
synchronized---------------------------------------------------
Object o=new Object();的内存布局
1.普通对象
由上而下,对象头{(markword),类型指针(class pointer)} ,实例数据(instance data),对齐(padding)。
a.markword,里面存储的是锁信息,GC信息【分代年龄(4 bit)】
b.类型指针(class pointer),指向你到底属于哪一个类(压缩成4字节)
c.实例数据(instance data),成员变量所存储的信息,,例如int i= 9;占4个字节
d.padding ,当字节数不能被8整除的时候,,补齐能被8整除(cpu在读内存里面值的时候,按照总线的宽度来读,被8整除,会特别顺,特别快,提高效率用的)
对于64bit的jvm来说,,指针长度为8个字节,此处默认压缩成(4个)
-XX:UseCompressedClassPointers 压缩指针
-XX:UseCompressedOops 普通对象指针 比如一个对象有个成员变量string,指向其他的地方,,默认也是压缩了的(4个字节)
当new 的时候,,无锁,-> 偏向锁 -> 轻量级锁(自旋锁) ->重量级锁
无锁 31bit hashCode 调用才生成 1bit偏向锁位,2bit锁标志位
偏向锁 当前线程指针JavaThread (线程id写到markword)
轻量级锁 只要有任意一个线程过来竞争,撤销偏向锁,指向线程栈中Lock Record的指针(线程栈生成Lock Record) CAS
&&如果当前线程异常,将会释放锁
volatile---------------------------------------------------
1.保证线程可见性
cpu的MESI缓存一致性协议
2.禁止指令重排序(内存屏障)
3.不能保证原子性
public class Singleton{
private static volatile Singleton INSTANCE;
private Singleton(){
}
public static Singleton getInstance() {
if( INSTANCE == null){
synchronized (this) {
if(INSTANCE ==null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
juc相关知识点
1.(递增操作)AtomicInterger atomic相关对象的操作,atomic无锁采用cas操作,所以大量操作时比synchronized效率高
LongAdder 相对于atomic 采用了分段锁
2.reentrantLock 可重入锁(底层为CAS操作,可以有不同的condition(等待队列))
public class ReentrantLockDemo {
Lock lock=new ReentrantLock();
//Lock lock=new ReentrantLock(true); //true表示公平锁
void m1() {
boolean locked=false;
try {
locked = lock.tryLock(5, TimeUnit.SECONDS);
//lock.lock();//synchronized(this)
} catch (Exception e) {
e.printStackTrace();
}finally {
if(locked)
lock.unlock();
}
}
}
3.读写锁ReentrantReadWriteLock
public class ReentrantLockDemo {
Lock lock=new ReentrantLock(true); //true表示公平锁
ReadWriteLock readWriteLock= new ReentrantReadWriteLock();
Lock readLock=readWriteLock.readLock();
Lock writeLock=readWriteLock.writeLock();
static int value;
public static void read(Lock lock) {
try {
lock.lock();
//lock.lock();//synchronized(this)
TimeUnit.SECONDS.sleep(1);
System.out.println("read over!");
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public static void write(Lock lock,int v) {
try {
lock.lock();
//lock.lock();//synchronized(this)
TimeUnit.SECONDS.sleep(1);
value=v;
System.out.println("write over!");
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
4,Semaphore信号灯
public static void main(String[] args) {
/*
* ReentrantLockDemo reentrantLockDemo=new ReentrantLockDemo(); new
* Thread(reentrantLockDemo::m1).start();
*/
Semaphore semaphore = new Semaphore(1);//类似于线程拿许可证
Runnable runnable=()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"running......");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName()+"running......");
} catch (Exception e) {
e.printStackTrace();
}finally {
semaphore.release();
}
};
new Thread(runnable).start();
new Thread(runnable).start();
}
5.LockSupport 当前线程阻塞,叫醒指定线程
public static void main(String[] args) {
Thread thread=new Thread(()->{
for (int i = 0; i < 10; i++) {
System.out.println(i);
if(i == 5) {
LockSupport.park();
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}) ;
thread.start();
//LockSupport.unpark(thread);可以先放行park
try {
TimeUnit.SECONDS.sleep(5);
System.out.println("5秒后....");
LockSupport.unpark(thread);
} catch (Exception e) {
e.printStackTrace();
}
}
6.生产者和消费者的问题,,condition为新起一个等待队列
public class ReentrantLockDemo {
Lock lock=new ReentrantLock(true); //true表示公平锁
Condition productCondition=lock.newCondition();
Condition consumerCondition=lock.newCondition();
LinkedList<Object> linkedList=new LinkedList<Object>();
int MAX=10;
int count=0;
public void put(Object o) {
try {
lock.lock();
while(linkedList.size() == MAX) {
productCondition.await();
}
linkedList.add(o);
++count;
productCondition.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
}
public Object get() {
Object object=null;
try {
lock.lock();
while(linkedList.size() == 0) {
consumerCondition.await();
}
object=linkedList.removeFirst();
count--;
consumerCondition.signalAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
lock.unlock();
}
return object;
}
}
7.ReentratLock内部原理,AQS,读源码
1.理解别人的思路,数据结构基础,设计模式
跑不起来不读
解决问题就好-目的性
一条线索到底
无关细节略过
一般不读静态
一般动态读法