【常用API】之并发性异常与锁、死锁
当多个线程,操作一个内容的时候,由于使用的是Runnable或Thread,
就需要定义全局公用的数据对象。
如果多个线程同时操作一个数据结果,
容易产生:并发性异常。
并发性异常:
数据超出了正常的范围。
解决这个问题,就需要 锁:synchronized
模拟一个售票系统,同时开启多个线程并加锁
package com.xzm.线程; public class _04_并发性异常与锁 { //主函数:售票大厅 public static void main(String[] args) { //创建线程:售票窗口 Thread t1 = new store("01窗口:"); Thread t2 = new store("02窗口:"); Thread t3 = new store("03窗口:"); Thread t4 = new store("04窗口:"); Thread t5 = new store("05窗口:"); //开窗售票 t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } } //================================================== //售票系统 //整个系统就是一个售票大厅 //每一个线程就是一个售票窗口 //只有50张票,5个窗口同时售票 //线程 class store extends Thread{ //窗口名称 private String name; //构造方法 public store(String name) { this.name = name; } //定义公用数据对象: //整个程序只能一个,50张票 public static int piao = 50; //公共的钥匙:只要是一个引用类型的对象的就可以 //随便是什么名字和类型:必须是引用的 //static:表示只能一把钥匙 public static String key="key"; //重写run方法:void,无返回 @Override public void run() { //不间断售票,售完结束,未知的。 while(true) { //创建锁的机制:synchronized //当一个线程操作数据的时候, //其他线程必须等待当前线程结束 //当前线程是锁定的,没有做完,别的线程不能执行。 //第一步:创建一把公共的钥匙 //第二步:创建锁,指定钥匙 //创建锁(钥匙),包住整个完整的操作 synchronized(store.key) { //判断 if(store.piao > 0) {//有 //打印票据 try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } store.piao--; System.out.println(this.name+"售出一张票,还剩:"+store.piao+"张。"); } else { System.out.println(this.name + "票已售完!"); break;//结束售票 } } } } }
死锁:
什么是死锁?
在多线程中,有多个线程,彼此在操作对象的时候相互锁定了。
有两个对象:
线程1:操作a,再操作b
线程2:操作b,再操作a
代码定义的时候需要注意:
1、尽量不要再多个线程中,同时定义多重的锁而且用的都是公用的钥匙
2、如果需要严格操作的,尽量减少嵌套锁机制
死锁实例:
package com.xzm.线程; public class _05_死锁实例 { //两个对象 public static String obj1 = "对象1"; public static String obj2 = "对象2"; //主函数 public static void main(String[] args) { //创建对象 LockA la = new LockA(); LockB lb = new LockB(); //创建线程,代入对象 Thread t1 = new Thread(la); Thread t2 = new Thread(lb); //运行 t1.start(); t2.start(); } } //====================================================== //线程一 class LockA implements Runnable{ //重写实现抽象方法 @Override public void run() { try { System.out.println("LockA 开始执行了"); while(true) { //先用1 synchronized(_05_死锁实例.obj1) { System.out.println("LockA 锁住了obj1"); Thread.currentThread().sleep(3000);//给另一个线程可以锁住的机会 //再用2 synchronized(_05_死锁实例.obj2) { System.out.println("LockA 锁住了obj2"); Thread.currentThread().sleep(1000*60);//位了测试,占用了就不放 } } } } catch(Exception ex) { ex.printStackTrace(); } } } //线程二 class LockB implements Runnable{ //重写实现抽象方法 @Override public void run() { try { System.out.println("LockB 开始执行了"); while(true) { //先用2 synchronized(_05_死锁实例.obj2) { System.out.println("LockB 锁住了obj2"); Thread.currentThread().sleep(3000);//给另一个线程可以锁住的机会 //再用1 synchronized(_05_死锁实例.obj1) { System.out.println("LockB 锁住了obj1"); Thread.currentThread().sleep(1000*60);//位了测试,占用了就不放 } } } } catch(Exception ex) { ex.printStackTrace(); } } }
唯一可以不劳而获的是贫穷,而唯一可以无中生有的是梦想。