【常用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();
        }
    }
}
原文地址:https://www.cnblogs.com/jiarenanhao/p/14133964.html