美文网首页
线程安全

线程安全

作者: Amy木婉清 | 来源:发表于2021-04-13 10:41 被阅读0次

    线程安全问题出现的根本原因和解决方案:

    线程安全问题出现的根本原因:

    1.必须要存在两个或者两个以上的线程共享着一个资源
    2.操作共享资源的代码必须有两句或者两句以上
    解决思路:
    就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程是不可以参与运算的。
    必须要当前线程把这些代码都执行完毕后,其他线程才能运算。
    同步的好处:解决了线程的安全问题。
    同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁。
    同步的前提:同步中必须有多个线程并使用同一个锁。

    解决方案: 1.同步函数 2.同步代码块
    1.同步代码块
     synchronized(锁){
                需要被同步的代码
            }
    
    class SaleTicket extends Thread{
         static int num = 50;//票数  非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。
         public SaleTicket(String name) {
            super(name);
        }
        
        @Override
        public void run() {
            while(true){
                //同步代码块
                synchronized ("锁") {                
                    if(num>0){
                        System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        num--;
                    }else{
                        System.out.println("售罄了..");
                        break;
                    }
                }           
            }
        }           
    } 
    public class Demo4 {    
        public static void main(String[] args) {
            //创建三个线程对象,模拟三个窗口
            SaleTicket thread1 = new SaleTicket("窗口1");
            SaleTicket thread2 = new SaleTicket("窗口2");
            SaleTicket thread3 = new SaleTicket("窗口3");
            //开启线程售票
            thread1.start();
            thread2.start();
            thread3.start();        
        }   
    }
    
    注意:

    1.同步代码块的锁可以是任意对象.同步函数的锁是固定的,非静态函数的锁是this对象.静态函数的锁是class对象。
    2.锁对象必须是多线程共享的对象,否则锁不住。
    3.在同步代码块或是同步函数中用sleep的方法是不会释放锁对象的,如果是调用了wait方法是会释放对象的。

    2.同步函数
       修饰符 synchronized 返回值类型   函数名(形参列表..){
    
            }
    
    class BankThread extends Thread{
        static int count = 5000;
        public BankThread(String name){
            super(name);
        }
        
        @Override  //
        public synchronized  void run() {
            while(true){
                synchronized ("锁") {                
                    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.如果函数是一个非静态的同步函数,那么锁对象是this对象;
    2.如果韩式是静态的同步函数,那么锁对象是当前函数所属的类的字节码文件(class对象);
    3.同步函数的锁对象是固定的,不能由自己指定。

    同步函数和同步代码块的区别:

    同步函数的锁是固定的this;
    同步代码块的锁是任意的对象。
    建议使用同步代码块。
    静态的同步函数使用的锁是该函数所属字节码文件对象
    可以用getClass()方法来获取,也可以使用当前类名.class表示。

    相关文章

      网友评论

          本文标题:线程安全

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