zoukankan      html  css  js  c++  java
  • 【常用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();
            }
        }
    }
  • 相关阅读:
    获取一张表的所有列
    SqlServer查询数据库所有用户表的记录数
    IE和Firefox在JavaScript方面的兼容性(转)
    ASP.NET2.0调用MySql的存储过程
    javascript在中ie与firefox的区别与解决方案(转)
    针对Firefox兼容性,要注意的一些问题 (转)
    JavaScript Import XML Document
    Remote建立分析
    sql2000和文本文件的写入和读取(转)
    firefox与IE对javascript和CSS的区别(转)
  • 原文地址:https://www.cnblogs.com/jiarenanhao/p/14133964.html
Copyright © 2011-2022 走看看