上篇文章说到了同步异步。那么在应用中同步异步的应用时候,设计程序时候,一定要注意业务的整体性。 也就是要注意上节学的资源的共享,则一定要同步。不然就会发生错误。比如经典的脏读(dirtyread)
脏读
概念: 对于对象的同步和异步的方法,我们在设计自己的程序时,一定要考虑问题的整体性,不然就会出现数据不一致的错误,很经典的就是脏读问题
packagecom.wkcto.intrinsiclock;/***脏读*出现读取属性值出现了一些意外,读取的是中间值,而不是修改之后的值*出现脏读的原因是对共享数据的修改与对共享数据的读取不同步*解决方法:*不仅对修改数据的代码块进行同步,还要对读取数据的代码块同步*Author:老崔*/publicclassTest08{publicstaticvoidmain(String[]args)throwsInterruptedException{//开启子线程设置用户名和密码PublicValuepublicValue=newPublicValue();SubThreadt1=newSubThread(publicValue);t1.start();//为了确定设置成功Thread.sleep(100);//在main线程中读取用户名,密码publicValue.getValue();}//定义线程,设置用户名和密码staticclassSubThreadextendsThread{privatePublicValuepublicValue;publicSubThread(PublicValuepublicValue){this.publicValue=publicValue;}@Overridepublicvoidrun(){publicValue.setValue("bjpowernode","123");}}staticclassPublicValue{privateStringname="wkcto";privateStringpwd="666";publicsynchronizedvoidgetValue(){System.out.println(Thread.currentThread().getName()+",getter--name:"+name+",--pwd:"+pwd);}publicsynchronizedvoidsetValue(Stringname,Stringpwd){this.name=name;try{Thread.sleep(1000);//模拟操作name属性需要一定时间}catch(InterruptedExceptione){e.printStackTrace();}this.pwd=pwd;System.out.println(Thread.currentThread().getName()+",setter--name:"+name+",--pwd:"+pwd);}}}
线程出现异常会自动释放锁
packagecom.wkcto.intrinsiclock;/***同步过程中线程出现异常,会自动释放锁对象**Author:老崔*/publicclassTest09{publicstaticvoidmain(String[]args){//先创建Test01对象,通过对象名调用mm()方法Test09obj=newTest09();//一个线程调用m1()方法newThread(newRunnable(){@Overridepublicvoidrun(){obj.m1();//使用的锁对象是Test06.class}}).start();//另一个线程调用sm2()方法newThread(newRunnable(){@Overridepublicvoidrun(){Test09.sm2();//使用的锁对象是Test06.class}}).start();}//定义方法,打印100行字符串publicvoidm1(){//使用当前类的运行时类对象作为锁对象,可以简单的理解为把Test06类的字节码文件作为锁对象synchronized(Test09.class){for(inti=1;i<=100;i++){System.out.println(Thread.currentThread().getName()+"-->"+i);if(i==50){Integer.parseInt("abc");//把字符串转换为int类型时,如果字符串不符合数字格式会产生异常}}}}//使用synchronized修饰静态方法,同步静态方法,默认运行时类Test06.class作为锁对象publicsynchronizedstaticvoidsm2(){for(inti=1;i<=100;i++){System.out.println(Thread.currentThread().getName()+"-->"+i);}}}
死锁
packagecom.wkcto.intrinsiclock;/***死锁*在多线程程序中,同步时可能需要使用多个锁,如果获得锁的顺序不一致,可能会导致死锁*如何避免死锁?*当需要获得多个锁时,所有线程获得锁的顺序保持一致即可*Author:老崔*/publicclassTest10{publicstaticvoidmain(String[]args){SubThreadt1=newSubThread();t1.setName("a");t1.start();SubThreadt2=newSubThread();t2.setName("b");t2.start();}staticclassSubThreadextendsThread{privatestaticfinalObjectlock1=newObject();privatestaticfinalObjectlock2=newObject();@Overridepublicvoidrun(){if("a".equals(Thread.currentThread().getName())){synchronized(lock1){System.out.println("a线程获得了lock1锁,还需要获得lock2锁");synchronized(lock2){System.out.println("a线程获得lock1后又获得了lock2,可以想干任何想干的事");}}}if("b".equals(Thread.currentThread().getName())){synchronized(lock2){System.out.println("b线程获得了lock2锁,还需要获得lock1锁");synchronized(lock1){System.out.println("b线程获得lock2后又获得了lock1,可以想干任何想干的事");}}}}}}