Lock锁
java.util.concurrent.locks
虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock。
1 2 3 4 | Lock: void lock(): 获取锁。 void unlock():释放锁。 ReentrantLock是Lock的实现类。 |
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class SellTicketDemo { public static void main(String[] args) { //创建线程对象 SellTicket st = new SellTicket(); //创建Thread对象 Thread t1 = new Thread(st,"窗口1"); Thread t2 = new Thread(st,"窗口2"); Thread t3 = new Thread(st,"窗口3"); //启动线程 t1.start(); t2.start(); t3.start(); } } |
自定义类实现Runnable接口
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 40 41 42 43 | public class SellTicket implements Runnable { //定义100张票 private int ticket = 100; //创建Lock锁对象 Lock lock = new ReentrantLock(); //Lock锁写法 @Override public void run() { while (true) { //开 lock.lock(); if (ticket > 0) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票"); } //关 lock.unlock(); } } //以前的写法 /*@Override public void run() { while (true){ synchronized (this) { if (ticket > 0) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票"); } } } }*/ } |
结果:
1 2 3 4 5 6 7 8 9 10 | 窗口1正在出售第10张票 窗口1正在出售第9张票 窗口3正在出售第8张票 窗口3正在出售第7张票 窗口3正在出售第6张票 窗口3正在出售第5张票 窗口3正在出售第4张票 窗口3正在出售第3张票 窗口3正在出售第2张票 窗口3正在出售第1张票 |
死锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 同步的弊端: A:效率低 B:容易产生死锁 死锁: 两个或两个以上的线程在争夺资源的过程中,发生的一种相互等待的现象。 举例: 中国人,美国人吃饭案例。 正常情况: 中国人:筷子两支 美国人:刀和叉 现在: 中国人:筷子1支,刀一把 美国人:筷子1支,叉一把 |
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 | public class DieLockDemo { public static void main(String[] args) { //创建线程对象 DieLock dl1 = new DieLock(true); DieLock dl2 = new DieLock(false); //启动线程 dl1.start(); dl2.start(); } } |
死锁代码演示
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 | public class DieLock extends Thread{ private boolean flag; public DieLock(boolean flag) { this.flag = flag; } //死锁代码演示 @Override public void run() { if (flag) { synchronized (MyLock.objA) { //线程tl1,进来关闭锁。 System.out.println("if objA"); synchronized (MyLock.objB) {//因为tl2锁已经关闭了,所以在等tl2执行完开锁。 System.out.println("if objB"); } } //出现了相互等待的情况,即死锁。 } else { synchronized (MyLock.objB) {//线程tl2,进来关闭锁。 System.out.println("else objB"); synchronized (MyLock.objA) {//因为tl1锁已经关闭了,所以在等tl1执行完开锁。 System.out.println("else objA"); } } } } } |
定义两把锁
1 2 3 4 | public class MyLock { public static final Object objA = new Object(); public static final Object objB= new Object(); } |
结果:出现死锁(是有可能出现)
1 2 | else objB if objA |