public
在java中到底是值传递还是引用传递这个问题,我想大家都已经知道了,不知道的可以自行查阅资料呦。
首先age=10;传入changeValue1()的方法中,然后被赋值成20,因为基本的数据类型都是在栈中,首先main方法进栈,然后changeValue1()方法进栈,执行完changeValue1()方法之后,就出栈了,所以输出的还是10;对于changeValue2(),传递的是一个对象,对象不在栈中,实例化的是在堆中,会指向一个地址,传到方法中后,依然会指向这个地址,所以修改的是对象的值,所以输出的是发发,对于changeValue3()传递一个字符串,这个大家可能会犯错,因为是直接字符串的赋值,所以首先会在常量池中去找,常量池中没有的话,会把abc放进去,changeValue3()中,str="XXX",在常量池中还是没有,所以还会放进去XXX,所以changeValue3()方法和main方法分别指向了不同的值,所以输出abc,如下图:
这下大家理解了吧,接下来说说java锁中公平锁和非公平锁。
java中的锁和mysql数据库的锁有一样的,也有不一样的,现在着重讲java中的锁。
首先大家应该了解ReentrantLock()是一个可重入锁。
Lock lock=new ReentrantLock();如果什么都不传,底层是不公平的,Lock lock=new ReentrantLock(true);这是公平的。
比如我们常见的Synchronized,它就是一个非公平的锁?为什么呢?因为在多线程的环境中,强占cpu的资源,假如有7个线程,第一次抢到的可能是3号线程抢到,3号线程释放锁之后,第二次这7个线程继续抢,有可能还是3号线程抢到,所以是非公平的锁。
对于ReentrantLock()来说,通过构造函数指定该锁是否是公平的,默认是非公平的。非公平锁的有点在于吞吐量比公平锁大。
公平锁:
获取不到锁的时候,会自动加入队列,等待线程释放后,队列的第一个线程获取锁
非公平锁:
获取不到锁的时候,会自动加入队列,等待线程释放锁后所有等待的线程同时去竞争
说到公平锁,就有必要谈谈什么是可重入锁。
可重入锁又名递归锁,最大的作用就是避免死锁,Synchronized和ReentrantLock都是非公平的可重入锁。
什么是可重入?
同一个线程可以反复获取锁多次,然后需要释放多次,指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,比如:进入method02()同步方法时会自动获取锁,
就好比进入你家家门,进家门是一把锁,进去之后,在进入你的卧室,会自动获取你卧室的锁,很形象吧。
下面说一下自旋锁,上篇文章也简单介绍过了,
自旋锁的好处:循环比较获取直到成功为止,没有类似wait的阻塞,自旋锁的核心就是比较并交换。来 手写一个自旋锁。
public class SpinLock {
AtomicReference<Thread> atomicReference=new AtomicReference<Thread>();
public static void main(String[] args) {
SpinLock spinLock = new SpinLock();
new Thread(()->{
spinLock.myLock();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.myUnLock();
},"AA").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
spinLock.myLock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
spinLock.myUnLock();
},"BB").start();
}
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"t come in");
while(!atomicReference.compareAndSet(null,thread)){
}
}
public void myUnLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
System.out.println(Thread.currentThread().getName()+"t invoked myUnLock");
}
}
以上都是锁的基本的知识,接下来的几篇文章会详细讲解以上的锁和独占锁(写锁)/共享锁(读锁)/互斥锁,后续几篇就先把并发这一块放放,先写点其他的知识,大家换换脑细胞,加油!