死锁
两个线程分别拿着对方的资源,不释放,形成僵持状态。
下面这个例子,是小花和小白一起化妆,小花先用口红,小白先用镜子,两个人拿到这两样东西后,不给对方,还问对方要对方的东西,形成了僵持状态
public class DeadLock {
public static void main(String[] args) {
girl g1 = new girl("小花",1);
girl g2 = new girl("小白",2);
g1.start();
g2.start();
}
}
class lipstick{
}
class mirror{
}
class girl extends Thread{
private static lipstick lipstick = new lipstick();
private static mirror mirror = new mirror();
int choice;
String name;
public girl(String name,int choice) {
super(name);
this.choice = choice;
}
public void run() {
makeup();
}
public void makeup()
{
if(choice == 1) {
synchronized(lipstick) {
System.out.println(Thread.currentThread().getName()+"得到了口红锁");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(mirror) {
System.out.println(Thread.currentThread().getName()+"得到了镜子锁");
}
}else {
synchronized(mirror) {
System.out.println(Thread.currentThread().getName()+"得到了镜子锁");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(lipstick) {
System.out.println(Thread.currentThread().getName()+"得到了口红锁");
}
}
}
}
死锁形成的必要条件:
互斥:某个资源在一段时间内只能由一个线程占有。
请求与保持:进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时(阻塞状态时),仍继续占用已占有的资源
不可抢占:进程所获得的资源在未使用完毕之前(被锁状态),资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放
循环等待:存在一个进程等待序列{P1,P2,…,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,…,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环
四个资源,四个线程:
线程1: 1、2、3、4
线程2: 2、3、4、1
线程3: 3、4、1、2
线程4: 4、1、2、3
线程1、2、3、4同时得到1、2、3、4资源
接下来线程1等线程2,线程2等线程3、线程3等线程4、线程4又等线程1
线程强制执行
Thread.join()方法,线程强制执行 其他线程进入阻塞状态,强制执行线程执行完之后,其他线程再进入就绪状态
//线程强制执行 其他线程进入阻塞状态,强制执行线程执行完之后,其他线程再进入就绪状态
//线程一旦执行完毕,是不可再start()的,因为已经将线程清理出栈区了
public class Testjoin {
public static void main(String[] args) {
Runnable r = new mRunnable();
Thread thread1 = new Thread(r,"线程1");
Thread thread2 = new Thread(r,"线程2");
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread2.start();
for(int i = 0;i<=100;i++) {
System.out.println(Thread.currentThread().getName() +"--"+ i);
}
}
}
class mRunnable implements Runnable{
private int i;
@Override
public void run() {
// TODO Auto-generated method stub
for(i = 0;i<=100;i++) {
System.out.println(Thread.currentThread().getName() + "--"+i);
}
}
}
线程礼让
线程礼让:让给其余线程先执行,但不一定礼让成功
礼让后,该线程进入阻塞状态,但很快会再次进入就绪状态
public class Testyield {
public static void main(String[] args) {
Thread thread = new Thread(()->{
for(int i = 0;i<=10;i++) {
System.out.println("副线程:"+i);
}
});
thread.start();
System.out.println(thread.getState());
thread.yield();
System.out.println(thread.getState());
try {
thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
System.out.println(thread.getState());
}
for(int i = 0;i<=10;i++) {
System.out.println("主线程:"+i);
}
System.out.println(Thread.currentThread().getState());
}
}
运行截图:
线程的四种状态:
NEW 创建状态
RUNNABLE 运行状态
TIMED_WAITING 阻塞状态
TERMINATED 结束状态