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(); } }