java小白的进阶之路

线程安全浅谈

2018-03-19  本文已影响6人  一只很懒很懒的虫

      首先了解下什么是线程,线程是一个程序中执行的最小单位,简单说它是一个任务。所有的线程共享一个内存空间。这就导致线程并发时存在线程安全的问题。那什么是线程安全呢?

      如果在并发多线程操作的时候每次得到的数据和单线程下得到的运行结果都一致的话,其他变量的值也和预期一样。那这样的情况就是线程安全的。反之,如果数据与预期不符,那就是可能在多线程并发时,多个线程同时修改数据,可能得到脏数据。

      引发线程安全问题的是因为共享资源引起的。具体来说就是共享变量和静态变量所引起的。

      先从jvm的内存模型开始了解。jvm一般在堆区存放共享资源,而同时每个线程都有一个独立的运行空间,存放局部变量,以及共享资源的一个副本。此时线程之间是相互独立的。当所有的线程都是只读状态,那么这个共享变量不会被修改,如果不仅读还有写的操作的话,就会存在安全问题。

      线程存储的共享变量副本,修改的值是不会时实更新到主存的,所以当有一个线程改变了该值,且没有结束线程,而另一个线程去读取时,并没有读到改变后的值。这就引发了对共享变量的可见性的问题。

      在java中作用到volatile来解决可见性问题。当线程在写时,立马更新到内存,当线程在读时,立马从内存中刷新。保证共享变量的数据时实性。

        除了可见性问题,还存在有序性问题导致线程的不安全。在单个线程中的代码执行顺序是有序的。但是多线程中有可能会交叉进行,这样导致数据不一致。

      比如a,b线程同时读取主存的值为10,a去改+1写然后放入主存此时为11,b去改-1为9再放入则主存的值为9。实际的预期是10+1-1还是10。

      为了解决这个问题,采用syncronized的同步锁的方式,将某个方法或者某个代码块锁定,然后让需要用到的线程同步执行,只有一个线程释放该模块,另一个才能进去执行。保证有序性。

      syncronized的锁分为对象锁和类锁,当作用于静态方法时采用的是类锁。而对象锁和类锁没有联系,可以同时使用。记住同步的是代码块或方法。其他的一律不会受到同步限制。

上一篇 下一篇

猜你喜欢

热点阅读