Java线程安全,什么是类的线程安全

  Java线程安全,什么是类的线程安全

  编写线程安全的代码,核心在于状态访问操作的管理,尤其是对共享和变量状态的访问。当多个线程访问一个状态变量,并且其中一个线程执行写操作时,必须采用同步机制来协调这些线程对该变量的访问。无状态对象必须是线程安全的。

  如何解决写爬虫IP受阻的问题?立即使用。

  如果我们在无状态的对象中增加一个状态时,会出现什么情况呢?

  假设我们向servlet添加一个“命中计数器”,以如下方式管理请求的数量:向servlet添加一个long字段,每次处理一个请求,该值就加1。

  公共类UnsafeCountingFactorizer实现Servlet {

  私有长计数=0;

  public long getCount() {

  返回计数;

  }

  @覆盖

  公共void服务(ServletRequest arg0,ServletResponse arg1)

  引发ServletException,IOException {

  //做点什么

  数数;

  }

  }不幸的是,上面的代码不是线程安全的,因为count不是原子操作。实际上,它包含三个独立的操作:读取count的值,将值加1,然后将计算结果写入count。如果线程A读取计数为10,线程B立即读取计数为10,线程A加1写入后为11。线程B已经将计数值读取为10,但是在加上1写入后仍然是11,因此丢失了一个计数。

  在并发编程中,这种由于执行顺序不当而导致的不正确结果是一种非常重要的情况,它有一个正式的名称:竞态条件。最常见的竞争条件是“执行前检查”操作,也就是说,下一个操作由可能无效的观察结果决定。

  延迟初始化是竞态条件的常见情形:

  公共类LazyInitRace {

  私有SomeObject实例=null

  公共SomeObject getInstance() {

  if(instance==null)

  instance=new SomeObject();

  返回实例;

  }

  }包含LazyInitRace中的竞态条件:首先线程A判断实例为null,然后线程B判断实例也为null。之后线程A和线程B分别创建对象,这样对象被初始化两次,出现错误。

  为了避免静态条件,当一个线程修改一个变量时,需要防止其他线程以某种方式使用该变量,以确保其他线程只能在修改操作完成之前或之后读取和修改状态,而不是在修改过程中。

  在UnsafeCountingFactorizer的情况下,线程不安全的原因是count不是原子操作。我们可以使用原子类来确保加法操作是原子的。

  这样类就是线程安全的了:

  公共类CountingFactorizer实现Servlet {

  private final atomic long count=new atomic long(0);

  public long getCount() {

  返回计数。get();

  }

  @覆盖

  公共void服务(ServletRequest arg0,ServletResponse arg1)

  引发ServletException,IOException {

  //做点什么

  count . incrementandget();

  }

  }AtomicLong是java.util.concurrent.atomic包中的原子变量类,可以实现原子的自动递增操作,所以是线程安全的。

  以上是什么java类是线程安全的细节。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: