1.多线程-线程安全问题演示

    多个线程对象运行同一个线程任务代码的时候,一个线程运行到判断语句后被临时阻塞了,下个线程继续判断,直接输出结果,前一个线程再输出的结果,可能会出问题

class Ticket implements Runnable{    private int num = 100;    public void run(){        while(true){            if(num>0){                try{                    Thread.sleep(10);                }catch(InterruptedException e){}                 //让线程在这里小睡,导致了 0 -1 等错误票的产生。                  //出现了线程安全问题。                System.out.println(Thread.currentThread().getName()+"..sale:"+num--);            }        }    }}

class ThreadDemo3_Ticket_Runnable{    public static void main(String[] args) {        Ticket t = new Ticket();                 Thread t1 = new Thread(t);        Thread t2 = new Thread(t);        Thread t3 = new Thread(t);        Thread t4 = new Thread(t);        t1.start();        t2.start();        t3.start();        t4.start();        //多个线程对象调用同一个线程任务    }}

2.多线程-线程安全问题原因

原因:

1.多个线程在同时处理共享数据。

2.线程任务中的有多条代码在操作共享数据。

 

安全问题成因就是:一个线程在通过多操作共享数据的过程中,其他线程参与了共享数据的操作。

    导致到了数据的错误.

 

想要知道你的多线程程序有没有安全问题:

    只要看线程任务中是否有多条代码在处理共享数据。

3.多线程-线程安全问题-同步代码块解决

解决:

    一个线程在通过多条语句操作共享数据的过程中,不允许其他线程参与运算。

 

如何代码体现呢?

    Java中提供了同步代码块进行引起安全问题的代码封装。

 

格式:

synchronized(对象) //该对象是任意的{    //需要被同步的代码;}

class Ticket implements Runnable{    private int num = 100;    Object obj = new Object();    public void run(){        while(true){            synchronized(obj){                if(num>0){                    try{                        Thread.sleep(10);                    }catch(InterruptedException e){}                                                                    System.out.println(Thread.currentThread().getName()+"..sale:"+num--);                }            }        }    }} class ThreadDemo4_Ticket_Safe{    public static void main(String[] args) {        Ticket t = new Ticket();                 Thread t1 = new Thread(t);        Thread t2 = new Thread(t);        Thread t3 = new Thread(t);        Thread t4 = new Thread(t);        t1.start();        t2.start();        t3.start();        t4.start();    }}

4.多线程-线程安全问题-同步代码块好处&弊端&前提

    同步好处:解决了多线程的安全问题。

    同步弊端:降低了效率。

     

    同步的前提:

        1.至少有两个线程在同步中。

        2.必须保证同步使用的是同一个锁。

     

     synchronized(new Object()){

        }

    意思是让每个线程进到同步代码块中,就会换一把新锁。有安全隐患,没有保障多线程直接使用用一把锁。

5.多线程-线程安全问题-同步函数使用的锁

    

同步的第二种表现形式:同步函数。

问题:同步函数使用的锁是什么呢?

    同步函数使用的锁,应该是this

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

    同步函数使用的固定锁this

    同步代码块使用的锁是可以指定的。

class Ticket implements Runnable{    private int num = 100;    boolean flag = true;    Object obj = new Object();    public void run(){        if(flag){            while(true){                synchronized(this){                    if(num>0){                        try{Thread.sleep(10);}catch(InterruptedException e){}                        System.out.println(Thread.currentThread().getName()+"..obj:"+num--);                     }                }            }        }else{            while(true){                this.sale();            }        }    }         public synchronized void sale(){//同步函数。        if(num>0){            try{Thread.sleep(10);}catch(InterruptedException e){}            System.out.println(Thread.currentThread().getName()+"..func:"+num--);        }    }}

class ThreadDemo5_Ticket_SynFunction{    public static void main(String[] args){        Ticket t = new Ticket();        Thread t1 = new Thread(t);        Thread t2 = new Thread(t);        t1.start();        try{Thread.sleep(10);}catch(InterruptedException e){}        t.flag = false;        t2.start();    }}

6.多线程-线程安全问题-静态同步函数使用的锁

静态同步函数使用的锁是什么?

   就是所在类的  类名.class   字节码文件对象。

class Ticket implements Runnable{    private static  int num = 100;    boolean flag = true;    public void run(){        if(flag){            while(true){                synchronized(Ticket.class)//super.getClass(){                if(num>0){                    try{Thread.sleep(10);}catch(InterruptedException e){}                    System.out.println(Thread.currentThread().getName()+"..obj:"+num--);                }            }        }else{            while(true) {                this.sale();            }         }       }     public static synchronized  void sale(){//static同步函数。        if(num>0){            try{Thread.sleep(10);}catch(InterruptedException e){}            System.out.println(Thread.currentThread().getName()+"..func:"+num--);        }     } } class ThreadDemo5_Ticket_StaticLock{    public static void main(String[] args) {        Ticket t = new Ticket();        Thread t1 = new Thread(t);        Thread t2 = new Thread(t);        t1.start();        try{Thread.sleep(10);}catch(InterruptedException e){}        t.flag = false;        t2.start();    }}

7.多线程-线程安全问题-单例懒汉式多线程问题

//饿汉式,不会出现线程安全问题,没有多条共享数据class Single1{    private static final Single1 s = new Single1();    private Single1(){}    public static Single1 getInstance(){        return s;    }}   //懒汉式 /*加同步关键字,解决的是安全问题。public static  Single getInstance() {if(s==null)  {s = new Single();} }加双重判断,是为了提高效率,不用每次都进入同步代码块。 */class Single2{    private static Single2 s = null;    private Single2(){}    public static  Single2 getInstance(){        //当存在对象时,执行到第一个if语句判断条件不符合后,不用进入下面的同步代码块        if(s==null){                synchronized(Single.class){                if(s==null){                    s = new Single();                }            }        }        return s;    }}

 

 

14-多线程-线程安全问题-死锁示例

 class Demo implements Runnable{    private boolean flag;        Demo(boolean flag){        this.flag = flag;    }         public void run(){        if(flag){            while(true){                synchronized(MyLock.LOCKA){                    System.out.println("if locka");                    synchronized(MyLock.LOCKB){                        System.out.println("if lockb");                    }                }            }        }else{            while(true){                synchronized(MyLock.LOCKB){                    System.out.println("else lockb");                    synchronized(MyLock.LOCKA){                        System.out.println("else locka");                    }                }            }        }    }}  class MyLock{    public static final Object LOCKA = new Object();    public static final Object LOCKB = new Object();}  class ThreadDemo8_DeadLock {    public static void main(String[] args) {        Demo d1 = new Demo(true);        Demo d2 = new Demo(false);        Thread t1 = new Thread(d1);        Thread t2 = new Thread(d2);        t1.start();        t2.start();    }}