Java多线程(2)——多线程安全(传智播客毕老师视频讲解)

来源:互联网 发布:软件测试工具使用 编辑:程序博客网 时间:2024/05/16 19:54

有如下代码

public class RunnableDemo2 implements Runnable{int i=10;public  void run(){for(;i>0;i--)System.out.println("...."+Thread.currentThread().getName()+"...."+i);}}public class Xian1 {static int i;public static void main(String[] args) {RunnableDemo2  t =new RunnableDemo2();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();t2.start();for(i=0;i<5;i++){System.out.println("...main......"+Thread.currentThread().getName());}System.out.println("over");}}
运行结果如下:

发现有两个10,且其排序不是按照从大到小输出的,此时这种情况属于多线程安全问题。其原因主要是线程0和线程1抢夺执行权引起的,

即当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据

的错误。

解决办法:对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可参与执行!

1、同步

同步的前提:1、必须要有两个或者两个以上的线程。

2、必须是多个线程使用同一个锁。


方法1、同步代码块

      synchonized(对象)//对象如同锁。持有锁的线程可以在同步中执行;没有锁的线程即使获取CPU执行权,也进不去。

      {

需要被同步的代码

       }

public class RunnableDemo2 implements Runnable{int i=10;public  void run(){synchronized(this){for(;i>0;i--)System.out.println("...."+Thread.currentThread().getName()+"...."+i);}}}
运行结果如下:

看见,此时结果没问题。

方法2、同步函数

public class RunnableDemo2 implements Runnable{int i=10;public  void run(){while(i>0)show();}public synchronized void show(){try{Thread.sleep(100);}catch(Exception e){}if(i>0)System.out.println("...."+Thread.currentThread().getName()+"...."+i--);}}

运行结果如下:

注意:1、同步函数用的锁是this!

    2、静态同步函数用的锁是Class对象!

  由于静态方法中不能出现this、super关键字,因此其锁不能为this,但可以是任意class对象!

验证代码如下:

public class RunanbleDemo implements Runnable{static int i=100;boolean flag=true;Object obj=new Object();public void setValue(boolean flag){this.flag=flag;}public  void run(){if (flag){while(true){synchronized(this)              //验证非静态同步函数的锁是this  //synchronized(RunanbleDemo.class)//验证静态同步函数的锁是Class文件{//同步代码块儿while(i>0){try{Thread.sleep(10);}catch(Exception e){}//try{wait();}catch(Exception e){}System.out.println("...."+Thread.currentThread().getName()+"...."+"Code"+"...."+i--);}}}}else{while(true)show();}} public synchronized void show()       //非静态同步函数   //public synchronized static void show()//静态同步函数{if(i>0){try{Thread.sleep(10);}catch(Exception e){}System.out.println("...."+Thread.currentThread().getName()+"..............."+"Show"+"...."+i--);}}}public class Xian1 {static int i;public static void main(String[] args) {RunanbleDemo  t =new RunanbleDemo();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();try{Thread.sleep(10);}catch(Exception e){}t.setValue(false);t2.start();System.out.println("over");}}
2、单例设计模式——懒汉式的多线程安全问题
方法1、同步函数

public class Single {private static Single s=null;private Single(){}public static synchronized Single getSingle(){if (s==null)s=new Single();return s;}}
方法2、同步代码块(优化版)
public class Single {private static Single s=null;private Single(){}public static  Single getSingle(){if (s==null)     //这是其优化的地方,这样保证假如许多线程进来,减少了判断syncronized的过程,优化了代码synchronized(Single.class){if (s==null)s=new Single();}return s;}}
3、死锁
public class DeadLock implements Runnable{static int i=100;boolean flag=true;Object obj=new Object();public void setValue(boolean flag){this.flag=flag;}public  void run(){if (flag){while(true){synchronized(DeadLock.class){synchronized(this)              //验证非静态同步函数的锁是this{if(i>0){try{Thread.sleep(10);}catch(Exception e){}System.out.println("...."+Thread.currentThread().getName()+"...."+"Code"+"...."+i--);}}}}}else{while(true){synchronized(this)               {synchronized(DeadLock.class){if(i>0){try{Thread.sleep(10);}catch(Exception e){}System.out.println("...."+Thread.currentThread().getName()+"..............."+"Show"+"...."+i--);}}  }}}}}public class DeadLockDemo {static int i;public static void main(String[] args) {DeadLock t =new DeadLock();Thread t1=new Thread(t);Thread t2=new Thread(t);t1.start();try{Thread.sleep(10);}catch(Exception e){}t.setValue(false);t2.start();System.out.println("over");}}
运行结果为:

即结果在97这儿锁死了,两个线程所持有的锁都不让对方进入,做开发时一定要避免死锁的出现!!





0 0
原创粉丝点击