1.锁的八种状态
2.公平锁和非公平锁
3.可重入锁的介绍(synchronized和lock)
4.死锁
锁的八种状态
锁的八种状态由这3种情况组合而成
1.对于普通的同步方法,锁的是当前的实例对象就是this
/**
* 对于普通的同步方法,锁的是当前的实例对象就是this
*/
public synchronized void hello1(){
System.out.println("hello");
}
2.对于静态同步方法,锁的是当前的Class对象
/**
* 对于静态同步方法,锁的是当前的Class对象
* @throws InterruptedException
*/
public static synchronized void hello() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("hello");
}
3.对于同步方法块,锁的时Synchronized括号里配置的对象
/**
* 对于同步方法块,锁的时Synchronized括号里配置的对象,对于当前来说就是this----->synchronized (this)
*/
public void hello3(){
synchronized (this){
System.out.println("hello");
}
}
公平锁和非公平锁
非公平锁会提升效率,但可能会使线程一直拿不到锁饿死(线程长时间得不到资源从而一直得不到执行)
公平锁:多个线程按照申请锁的顺序进入队列,从而的到锁
ReentrantLock默认是非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
可重入锁
使用synchronized来验证可重入锁
public synchronized void add(){
add();
}
而它报错的内容为堆栈溢出,但说明了它是可重入锁
而对于Lock来说
public void get(){
try {
LOCK.lock();
System.out.println(Thread.currentThread().getName()+"我在外层");
try {
LOCK.lock();
System.out.println(Thread.currentThread().getName()+"我在内层");
}finally {
LOCK.unlock();
}
}finally {
LOCK.unlock();
}
}
结果可以打印出来,说明Lock也是可重入锁
死锁
死锁的产生是多个线程互相持有资源得不到释放
下面来具体演示一下
线程aa持有o1,想要获取o2
线程bb持有o2,想要获取o1
代码:
Object o1 = new Object();
Object o2 = new Object();
new Thread(()->{
synchronized (o1){
System.out.println("线程"+Thread.currentThread().getName()+"持有o1,想要得到o2");
synchronized (o2){
System.out.println("获取o2");
}
}
},"aa").start();
new Thread(()->{
synchronized (o2){
System.out.println("线程"+Thread.currentThread().getName()+"持有o2,想要得到o1");
synchronized (o1){
System.out.println("获取o1");
}
}
},"bb").start();
运行结果如图所示,程序一直没有
但这个可能也不是死锁,比如死循环,或者睡眠也有一样的结果,即我们只有两个工具jps和jstack(必须配置环境变量)
使用jps获取到当前类的进程号 jps -l
我的类是demo11,从而进程号为20244
使用这个命令 jstack 20244,在最后的结果处就有相应的显示
Found 1 deadlock. 发现一个死锁,即从而确定死锁
如果需要这个demo,就来获取:https://gitee.com/wuwenlei/annotation-development/blob/dev/spring-annotation/src/main/java/com/springannotation/sync/demo11.java