Java线程安全总结

发表于:2011-10-18 09:28

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:jameswxx    来源:51Testing软件测试网采编

分享:

  执行结果:

  Html代码

  • 放入鸡蛋   
  • 拿到鸡蛋   
  • 放入鸡蛋   
  • 拿到鸡蛋   
  • 放入鸡蛋   
  • 拿到鸡蛋   
  • 放入鸡蛋   
  • 拿到鸡蛋   
  • 放入鸡蛋   
  • 拿到鸡蛋   
  • 测试结束
  •   声明一个Plate对象为plate,被线程A和线程B共享,A专门放鸡蛋,B专门拿鸡蛋。假设

      1、开始,A调用plate.putEgg方法,此时eggs.size()为0,因此顺利将鸡蛋放到盘子,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列还没有线程。

      2、又有一个A线程对象调用plate.putEgg方法,此时eggs.size()不为0,调用wait()方法,自己进入了锁对象的阻塞队列。

      3、此时,来了一个B线程对象,调用plate.getEgg方法,eggs.size()不为0,顺利的拿到了一个鸡蛋,还执行了notify()方法,唤醒锁的阻塞队列的线程,此时阻塞队列有一个A线程对象,唤醒后,它进入到就绪队列,就绪队列也就它一个,因此马上得到锁,开始往盘子里放鸡蛋,此时盘子是空的,因此放鸡蛋成功。

      4、假设接着来了线程A,就重复2;假设来料线程B,就重复3。

      整个过程都保证了放鸡蛋,拿鸡蛋,放鸡蛋,拿鸡蛋。

      volatile关键字

      volatile是java提供的一种同步手段,只不过它是轻量级的同步,为什么这么说,因为volatile只能保证多线程的内存可见性,不能保证多线程的执行有序性。而最彻底的同步要保证有序性和可见性,例如synchronized。任何被volatile修饰的变量,都不拷贝副本到工作内存,任何修改都及时写在主存。因此对于Valatile修饰的变量的修改,所有线程马上就能看到,但是volatile不能保证对变量的修改是有序的。什么意思呢?假如有这样的代码:

      Java代码

    public class VolatileTest{  
      public volatile int a;  
      public void add(int count){  
           a=a+count;  
      }  
    }

      当一个VolatileTest对象被多个线程共享,a的值不一定是正确的,因为a=a+count包含了好几步操作,而此时多个线程的执行是无序的,因为没有任何机制来保证多个线程的执行有序性和原子性。volatile存在的意义是,任何线程对a的修改,都会马上被其他线程读取到,因为直接操作主存,没有线程对工作内存和主存的同步。所以,volatile的使用场景是有限的,在有限的一些情形下可以使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:

      1)对变量的写操作不依赖于当前值。

      2)该变量没有包含在具有其他变量的不变式中

      volatile只保证了可见性,所以Volatile适合直接赋值的场景,如

      Java代码

    public class VolatileTest{  
      public volatile int a;  
      public void setA(int a){  
          this.a=a;  
      }  
    }

      在没有volatile声明时,多线程环境下,a的最终值不一定是正确的,因为this.a=a;涉及到给a赋值和将a同步回主存的步骤,这个顺序可能被打乱。如果用volatile声明了,读取主存副本到工作内存和同步a到主存的步骤,相当于是一个原子操作。所以简单来说,volatile适合这种场景:一个变量被多个线程共享,线程直接给这个变量赋值。这是一种很简单的同步场景,这时候使用volatile的开销将会非常小。

    44/4<1234
    重磅发布,2022软件测试行业现状调查报告~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号