Java并发之线程安全性

  1. 什么是线程安全?
  2. 造成线程安全的因素?
  3. 为什么要保证线程安全?
  4. 怎么保证线程安全?
  5. 什么时候需要线程安全?

什么是线程安全呢?
线程安全性的定义中,最核心的概念就是正确性,如果对线程安全的定义是模糊的,那么就是因为缺乏对正确性的清晰定义。所谓的正确性就是说:某个类的行为与其规范完全一致。在对正确性给出了较为清晰的定义后,就可以定义线程安全性:当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类时线程安全类。

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协调,这个类就能表现出正确的行为,那么就称这个类是线程安全的。

造成线程安全的因素?
主要有两点:

  1. 共享资源(Shared)
  2. 可变资源(Mutable)

    为什么要保证线程安全?
    其实就一个根本原因:保证各个线程访问的正确性

    怎么保证线程安全?

如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么线程就会出现错误。有三种方式可以保证安全性:
1.不在线程之前共享该变量的状态
2.将状态变量修改为不可变的变量
3.在访问状态变量时使用同步

什么时候需要线程安全?
一句话概括:
一个对象是否需要时线程安全的,取决于它是否需要被多个线程访问。

其它相关概念:
原子性
原子性的操作一定是安全的

public class UnsafeCountingFactorizer implements Servlet{
    private long count = 0;
    public long getCount(){
        return this.count;
    }
    public void service(ServletRequest req, ServletResponse resp){
    BigInteger i = extractFromRequest(req);
    BigInteger [] factors = factor(i);
    ++count;
    encodeIntoResponse(resp,factors);
    }
}

UnsafeCountingFactorizer 是线程非安全的,尽管它在单线程环境中能够正确的执行。++count看上去是一个紧凑的语法,其实这个操作是非原子操作,它包含三个操作步骤:读取-修改-写入,并且其结果依赖于之前的状态。所有在多线程方式访问下和可能会丢失一些更新操作。
资源竞争
既然多个线程访问共享的资源或者可变资源,那么资源只有一个多个线程访问是必须要有竞争
竞态条件
当某个计算的结果的真确性取决于多个线程的交替执行的时序时,那么就发生竞态条件。

通俗点将就是 正确的结果要按照正确的顺序执行

内置锁
Java提供了一种内置锁的机制来支持原子性:同步代码块(Synchronized Block)

synchronzied(loc){}

重入
当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞。然而,由于内置锁时可以重入的,因此如果某个线程试图获得由它自己持有的锁,那么这个请求就会成功
代码示例:

public class Widget{
    public synchronzied void doSomething(){
        //相关业务处理
    }
}

public class LoggingWidget extends Widget{
    public synchroinzed void doSomething(){
        super.doSomething()
    }
}

如果内置锁是不可重入的,则上面的代码将发生死锁

注意事项

1.对于可能被多个线程同时访问的可变状态变量,在访问它时都需要持有同一个锁,在这种情况下,我们称状态变量是由这个锁保护的。
2.每个共享的和可变的变量都应该只由一个锁来保护,从而使维护人员知道是哪一个锁。
3.对于每个包含多个变量的不变性条件,其中涉及的所有变量都需要有同一个锁来保护。
4.当执行时间较长的计算或者可能无法快速完成的操作(例如:网络IO或者控制台IO),一定不要持有锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值