为啥局部变量是安全的?
线程中的局部变量的作用范围只是在方法内部,方法的执行对应栈帧的入栈和出栈,也就是变量是在一个栈帧中的。局部变量分配在栈中,因此不会被其他线程访问到。这个变量是线程私有的。因此是安全的。
Java中的对象和数组都是在堆上分配的吗?
不一定,因此JVM会进行逃逸分析,分析出一个新对象的使用范围,并以此确定是否将这个对象分配到堆上,如果这个对象的使用范围只是在方法内部,那么很有可能会被优化分配在栈中。
逃逸分析:逃逸分析会判断新建的对象是否逃逸出方法
synchronized
1.反编译后,monitorenter、monitorexit、ACC_SYNCHRONIZED
synchronized作用于代码块时,通过反编译,字节码中会出现monitorenter、monitorexit,JVM通过monitorenter和monitorexit进行同步,monitorenter用来获得锁,monitorexit释放锁;如果synchronized作用于方法,反编译可以看到在方法的访问标识符中看到ACC_SYNCHRONIZED标记,线程执行带有这个标志的方法时,需要获得monitor锁,每个对象都与monitor关联,线程可以占有或者释放monitor。
Java中提供了synchronized为什么还提供Lock呢?
因为synchronized加锁是无法主动释放锁的,有可能造成死锁的问题。
死锁的条件:互斥、不可抢占、占有并等待、循环等待
如果是synchronized来加锁,那么造成死锁时,synchronized是无法破坏不可抢占这个条件,会一直阻塞下去,也不能释放线程已经占用的资源。
但是Lock类可以提供响应中断、支持超时、非阻塞的获取锁。
lockInterruptibly() :支持中断
tryLock():非阻塞的获取锁
tryLock(time,unit):支持超时释放锁
对于死锁问题,Lock可以破坏不可抢占这个条件
StringBuffer、StringBuilder、String
操作少量的数据 String
单线程下大量的数据,StringBuilder
多线程下大量的数据,StringBuffer
单例模式
public class Single
{
private volatile static Single uniqueInstance;
private Single(){
}
public static Single getUniqueInstance(){
if(uniqueInstance==null){
synchronized(Single.class){
if(uniqueInstance==null){
uniqueInstance = new Single();
}
}
}
return uniqueInstance;
}
}