美文网首页
java 线程安全问题的解决办法 和死锁

java 线程安全问题的解决办法 和死锁

作者: 发光驴子 | 来源:发表于2018-03-08 00:40 被阅读0次

    线程安全问题的解决办法

    线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。

    java线程同步机制的方式:
    方式一:同步代码块

            同步代码块的格式:
                
                synchronized(锁对象){
                    需要被同步的代码...
                }
    

    同步代码块要注意事项:
    1. 任意的一个对象都可以做为锁对象。
    2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
    3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
    4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。

        class SaleTicket extends Thread{
     static int num = 50;//票数  非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。
     
     static Object o = new Object();
    
     public SaleTicket(String name) {
        super(name);
    }
    
    @Override
    public void run() {
        while(true){
            //同步代码块
            synchronized ("锁") {//任意的一个对象都可以做为锁对象。对象为Static,但String特殊,因为字符串就是在字符串常量池中。              
                if(num>0){
                    System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
                    try {
                        Thread.sleep(100);//在同步代码块中调用了sleep方法并不是释放锁对象的。
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num--;
                }else{
                    System.out.println("售罄了..");
                    break;
                }
            }
            
        }
    }   
    
    
    } 
    
    
    public class Thread_02 {
    
    public static void main(String[] args) {
        String s =new String("abc");
        String str1 = "abc"; 
        System.out.println(str1 ==s);
        //创建三个线程对象,模拟三个窗口
        SaleTicket thread1 = new SaleTicket("窗口1");
        SaleTicket thread2 = new SaleTicket("窗口2");
        SaleTicket thread3 = new SaleTicket("窗口3");
        //开启线程售票
        thread1.start();
        thread2.start();
        thread3.start();
        
    }
    
      }
    

    方式二:同步函数
    同步函数就是使用synchronized修饰一个函数。

    同步函数要注意的事项 :
        1. 如果是一个非静态的同步函数的锁 对象是this对象(ps:这样会存在锁不住的情况,因为俩个对象调用同一个文件,就会出现俩个锁),如果是静态的同步函数的锁 对象是当前函数所属的类的字节码文件(class对象)。
        2. 同步函数的锁对象是固定的,不能由你来指定 的。
    
    
    推荐使用: 同步代码块。
        原因:
            1. 同步代码块的锁对象可以由我们随意指定,方便控制。同步函数的锁对象是固定 的,不能由我们来指定。
            2. 同步代码块可以很方便控制需要被同步代码的范围,同步函数必须是整个函数 的所有代码都被同步了。
    class BankThread extends Thread{
    
    static  int count = 5000;
    
    public BankThread(String name){
        super(name);
    }
    
    @Override  //
    public void run() {
        getMoney();//这样也锁定住,但是会造成只能一个人取完全部的钱,因为只有循环结束,才会释放锁
    }   
    
    
    //静态的函数---->函数所属 的类的字节码文件对象--->BankThread.class  唯一的。
    public static synchronized  void getMoney(){
        while(true){            
                if(count>0){
                    System.out.println(Thread.currentThread().getName()+"取走了1000块,还剩余"+(count-1000)+"元");
                    count= count - 1000;
                }else{
                    System.out.println("取光了...");
                    break;
                }
            
        }
    }
    
     }
    
    
      public class Demo1 {
    
    public static void main(String[] args) {
        //创建两个线程对象
        BankThread thread1 = new BankThread("老公");
        BankThread thread2 = new BankThread("老婆");
        //调用start方法开启线程取钱
        thread1.start();
        thread2.start();
        
        
    }
    
    }       
    

    出现线程安全问题的根本原因:
    1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
    2. 有多个语句操作了共享资源。

    线程的死锁

    /*
     * java 中同步机制解决了线程安全问题,但是同时引发死锁现象
     * 
     * 死锁现象:就是 俩个或者俩个以上线程,共同调用俩个或者以上的资源,发生共同等待的状态
     * 
     * 死锁现象的出现的根本原因:
     * 1.存在俩个或者俩个以上的线程
     * 2.存在俩个或者俩个以上的共享资源
     * 
     * 死锁现象的解决方案:没有方案,只能尽量避免发生而已
    
    */
    
    class DeadLock extends Thread{
        public DeadLock(String name){
            super(name);
        }
    
        public void run(){
            if("张三".equals(Thread.currentThread().getName())){
                synchronized ("遥控器") {
                    System.out.println("张三拿到了遥控器,准备去拿电池!!");
                    synchronized ("电池") {
                        System.out.println("张三拿到了遥控器和电池,开始吹空调");
                    }
                }
            
            }else if("李四".equals(this.getName())){
                synchronized ("电池") {
                    System.out.println("李四拿到了电池,准备去那遥控器");
                    synchronized ("遥控器") {
                        System.out.println("李四拿到了遥控器和电池,开始吹空调");
                    }
                }
            
            }
        }
    }
    public class Thread_04 {
        public static void main(String[] args) {
                DeadLock l1=new DeadLock("张三");
            DeadLock l2=new DeadLock("李四");
            l1.start();
            l2.start();
    }
    
    }

    相关文章

      网友评论

          本文标题:java 线程安全问题的解决办法 和死锁

          本文链接:https://www.haomeiwen.com/subject/zswzxftx.html