线程安全性

线程的使用一直是难以把控掌握的。如果使用得当,线程可以有效地降低程序的开发和维护等成本,同时提升复杂应用程序的性能。在GUI应用程序中,提高用户界面的响应灵敏度,在服务器应用程序中,提升资源利用率以及系统吞吐量。

     然而,如果使用不当,线程将会带来一系列不可预估的风险。Java对线程的支持其实就是一把双刃剑。虽然Java明确是一种跨平台(编写异常,随处运行)的语言,JDK并提供了相应的类库,简化了程序的开发,但更多的在处理一些复杂程序时,就需要使用线程,随之引入的“并发性”问题(线程安全性),就成为了开发人员实现考虑的难点。

    在多线程中的各个操作的顺序都是不可预测的,有时其执行结果简直出乎意料,令人惊讶。例如,通过下面代码片段的数值序列生成器,用来生成一个递增序列。

    package com.xcbeyond.thread;
     
    import net.jcip.annotations.NotThreadSafe;
     
    /**
     * 非线程安全的数值序列生成器
     * @author xcbeyond
     * 2018-5-6下午03:17:33
     */
    public class UnSafeThreadSequence {
        private int value;
        
        /**
         * 返回一个唯一的值
         * @return
         */
        public int getValue() {
            return value++;
        }
    }

       

     如果在单线程中执行,没有任何问题,结果也正如我们预期的一样。而在多线程并发的场景下操作,将会出现不同线程之间交替操作,不同线程很可能同时读取同一个值,得到相同值,导致不同线程返回了相同的序列值,这恰恰与我们的预期截然相反。

     这充分说明了一种常见的线程并发危险:竞争条件。因为线程共享了相同的内存空间地址,且并发的执行,它们可能访问或修改其他线程正在使用的变量,将会出现变量竞争情况。

       线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。


     如何编写线程安全的代码呢?

    编写线程安全的代码,核心在于要对状态访问操作进行管理,特别是对共享的(Shared)和可变的(Mutable)状态的访问。一个对象是否需要时线程安全的,取决于该对象是否被多线程访问。这指的是程序中访问对象的方式,而不是对象要实现的功能。要使得对象是线程安全的,要采用同步机制来协同对对象可变状态的访问。Java常用的同步机制是Synchronized,还包括 volatile类型的变量,显示锁以及原子变量。

原子性:

      假定有两个操作A和B,如果从执行A的线程来看,当另一个线程执行B时,要么将B完全执行完,要么完全不执行B,那么A和B对彼此来说是原子的。原子操作是指:对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作。

      竞态条件(Race Condition):某个计算/程序的正确性取决于多个线程的交替执行的时序。(线程的时序不同,产生的结果可能会不同)
  “先检查后执行”,即通过一个潜在的过渡值来决定下一步的操作。

     首先观察到某个条件为真,然后开始执行相关的程序,但是在多线程的运行环境中,条件判断的结果以及开始执行程序中间,观察结果可能变得无效(另外一个线程在此期间执行了相关的动作),从而导致无效。

     “读取-修改-写入”,基于对象之前的状态来定义对象状态的转换。即使是volatile修饰的变量,在多线程的环境里面进行自增操作,同样会发生竞态条件,所以volatile不能保证绝对的线程安全。
加锁机制:

 更多详见:http://www.mark-to-win.com/tutorial/50306.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值