1、重入锁
所谓的可重入锁,就是说当一个线程进入到同步代码时,然后再在这个代码块里面再去申请同一把锁,此时还能申请得到,这就是可重入锁。
案例:
2、自旋锁(非重入锁)
所谓的自旋锁就是说:若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞。
示例:
package com.xnn.thread.t6;
import java.util.Random;
/**
* 类(接口)描述:多个线程执行完毕后,就打印一句话 :结束所有线程
* @author xnn
* 2019年3月17日下午1:52:29
*/
public class Demo2 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"这个线程开始执行");
try {
Thread.sleep(new Random().nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"这个线程开始执行");
try {
Thread.sleep(new Random().nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"这个线程开始执行");
try {
Thread.sleep(new Random().nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束");
}
}).start();
while(Thread.activeCount()!=1) {
//自旋,就是空转CPU。
}
当Thread.activeCount()==1时,就说明只剩下主线程了。此时按照我们的需求 才可以打印下面的呢句话
System.out.println("所有的线程执行完毕了");
}
}
注:Thread.activeCount()是代表当前活动线程的数。、
3、死锁
死锁即你拿着我需要的资源,我拿着你所需要的资源,并且还都不释放。此时就会造成死锁。
造成死锁的几个必要条件:
互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
类比到多线程的环境下亦是如此。
示例:
package com.xnn.thread.t6;
/**
* 类(接口)描述:死锁现象演示
* @author xnn
* 2019年3月17日下午2:02:15
*/
public class Democrat {
private Object obj1 =new Object();
private Object obj2 =new Object();
public void a() {
synchronized (obj1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//在a方法的同步代码块中又去申请锁2
synchronized (obj2) {
System.out.println("a");
}
}
}
public void b() {
synchronized (obj2) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//在b方法的同步代码块中又去申请锁1
synchronized (obj1) {
System.out.println("b");
}
}
}
public static void main(String[] args) {
Democrat d = new Democrat();
//创建两个线程,一个执行a方法 一个执行b方法
new Thread(new Runnable() {
@Override
public void run() {
d.a();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
d.b();
}
}).start();
}
}