多线程的安全问题: 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。 解决的办法: 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其它线程不可以参与执行。 Java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。 synchronized(对象) { 需要被同步的代码 } 例子: synchronized(obj){ if(tick>0){ try { Thread.sleep(10); } catch (Exception e){} System.out.println(Thread.currentThread().getName()+ "...sale:"+tick--); } 对象如同锁。持有锁的线程可以在同步中执行,没有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
同步函数使用的是this锁。 函数需要被对象调用,那么函数都有一个所属对象引用,就是this。 例子: public void run(){ this.show(); } public synchronized void show(){ if(tick > 0){ try{ Thread.sleep(10); } catch(Exception e){} } System.out.println(Thread.currentThread().getName()+ "...show....:"+tick--); } } 同步函数被静态修饰后,使用的锁是什么呢? 通过验证,发现不再是this,因为静态方法中也不可以定义this。 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象,类名.class,该对象的类型是Class。 静态的同步方法,使用的锁是该方法所在类的字节码文件对象,类名.class。 例子: class Ticket implements Runnable{ private static int tick = 100; boolean flag = true; public void run(){ if(flag){ while(true){ synchronized(Ticket.class){ if(tick > 0){ try{ Thread.sleep(10); } catch(Exception e){ System.out.println(Thread.currentThread(). getName()+"...code:"+tick--); } } } } else while(true) show(); } public static synchronized void show(){ if(tick > 0){ try{ Thread.sleep(10); } catch(Exception e){} System.out.println(Thread.currentThread().getName()+ "...show....:"+tick--); } } }
|