首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“线程安全”到底是什么意思?

“线程安全”到底是什么意思?
EN

Stack Overflow用户
提问于 2014-02-18 14:56:15
回答 2查看 636关注 0票数 1

在实践中来自Java并发:

代码语言:javascript
复制
package net.jcip.examples;

import java.util.concurrent.atomic.*;

/**
 * NumberRange
 * <p/>
 * Number range class that does not sufficiently protect its invariants
 *
 * @author Brian Goetz and Tim Peierls
 */


public class NumberRange {

    // INVARIANT: lower <= upper
    private final AtomicInteger lower = new AtomicInteger(0);
    private final AtomicInteger upper = new AtomicInteger(0);

    public void setLower(int i) {
        // Warning -- unsafe check-then-act
        if (i > upper.get())
            throw new IllegalArgumentException("can't set lower to " + i + " > upper");
        lower.set(i);
    }

    public void setUpper(int i) {
        // Warning -- unsafe check-then-act
        if (i < lower.get())
            throw new IllegalArgumentException("can't set upper to " + i + " < lower");
        upper.set(i);
    }

    public boolean isInRange(int i) {
        return (i >= lower.get() && i <= upper.get());
    }
}

它说:“setLowersetUpper都是检查-然后动作序列,但它们没有使用足够的锁定使它们具有原子性。如果数字范围保持在(0,10),而一个线程调用setLower(5),而另一个线程调用setUpper(4),则带有一些不吉利的时间的线程都将通过设置器中的检查,并且都将应用这两种修改。结果是,范围现在保持(5,4)无效状态。“

如果AtomicInteger是线程安全的,那么它怎么会发生呢?以及如何解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-18 15:33:06

AtomicInteger的参与与您问题的线程安全性无关。

以下是问题所在:

  1. 如果(i > upper.get)
  2. lower.set(i);

步骤1和步骤2可以是单独的原子化的,但是它们一起形成两个步骤,非原子的动作。

以下是可能发生的情况:

  1. 如果我错了
  2. 上下文切换到另一个线程。
  3. 另一个线程调用upper.set(q),从而使q
  4. 上下文切换回此线程。
  5. 较低的设置为i。

每个单独的步骤本质上都是原子的,但是步骤的集合不是原子的。

用于此的java解决方案是:

  1. 同步(some_object_reference,也许这个)
  2. {
  3. 如果(i > upper.get)
  4. lower.set(i)
  5. }

请确保使用相同的对象引用来同步上值和下值的所有设置。

票数 1
EN

Stack Overflow用户

发布于 2014-02-18 15:42:16

让我们创建一个对象:

代码语言:javascript
复制
NumberRange nr= new NumberRange();

线程A:

代码语言:javascript
复制
nr.setLower(-1); //A1

线程B:

代码语言:javascript
复制
nr.setLower(-3); //B1
nr.setUpper(-2); //B2

执行顺序: B1,然后是A1和B2,同时:如果线程B在A (-3 < -2)之前通过检查,然后A在B设置值(-1 < 0)之前通过检查,则此代码不会抛出任何错误,因为您的方法不是原子的。检查是原子的,set方法也是原子的,但是总共有两个原子步骤,而不是一个。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21857424

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档