互斥锁
每一个对象都对应一个可称为“互斥锁”的标记,这个标记用来保证任意时刻,只有一个线程可以访问该对象,但是会导致执行效率比较低,同步方法的锁可以是this,也可以是其他对象,同步方法的锁为当前类的本身。上面买票的问题可以是this本身,也可以object,但是必须同一个对象,不可以是new的多个对象。
如果在静态代码中,必须当前对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| class AA implements Runnable{ public static void sell() { synchronized (AA.class){ } }
@Override public void run() { } }
|
线程死锁
多线程占用对方的资源,但是不肯相让,导致了死锁。线程一直得不到资源,而一直在相互等待。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
public class Test { public static void main(String[] args) throws InterruptedException { Block block=new Block(true); Block block1=new Block(false); block.start(); block1.start(); } } class Block extends Thread{ boolean flag; static Object object1=new Object(); static Object object2=new Object(); public Block(boolean flag){ this.flag=flag; } @Override public void run() { if (flag){ synchronized (object1){ System.out.println("a我进入到了1"); synchronized (object2){ System.out.println("a我进入到了2"); } } } else { synchronized (object2) { System.out.println("b我进入到了2");
synchronized (object1) { System.out.println("b我进入到了1"); } } } } }
|
可以看到程序一直卡在这里等待对方释放资源
释放锁
- 当前线程的同步方法,同步代码块执行结束(正常的执行结束)
- 当前线程在同步代码块,同步方法中遇到return,break(不得已而出来)
- 当前线程在同步代码块,或者方法遇到了未处理的错误或者异常,导致异常结束
- 当前线程在同步代码块,同步方法中执行了对象的wait方法,当前线程暂停,注意但是sleep方法不会释放锁
- 不会释放锁:线程执行同步代码块或者同步方法时,程序调用sleep,yield方法会暂停当前线程的执行,不会释放锁
- 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。
练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import java.util.Scanner;
public class Test { public static void main(String[] args) throws InterruptedException { Num num=new Num(); num.start();
Scanner scanner=new Scanner(System.in); while (true) { String letter = scanner.next(); if (letter.equals("Q")) { System.out.println("程序结束"); num.flag=false; break; } } } } class Num extends Thread{ boolean flag=true;
@Override public void run() { while (flag){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Math.round(Math.random()*100)); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public class Test { public static void main(String[] args) { Credit credit=new Credit(); Thread thread=new Thread(credit); Thread thread1=new Thread(credit); thread.start(); thread1.start(); } } class Credit implements Runnable{ double balance=1000.00; static Object object=new Object(); @Override public void run() { while (true){ synchronized (object){ if (balance<=0){ System.out.println("您的余额不足"); break; }
balance=balance-100; System.out.println(Thread.currentThread().getName()+"取出100元,还剩"+balance); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
} }
|