在从另一个线程读取时,是否有可能读取到非易失性变量的旧值?

huangapple go评论81阅读模式
英文:

Is it possible to read stale value of non-volatile variable during read from another thread?

问题

以下是您提供的内容的中文翻译:

我有一个主线程,它构造了一个带有非volatile变量的对象,然后在此线程中我改变了变量的值,并将对象放入BlockingQueue中。
在第二个线程中,我等待直到对象可用,然后读取对象及其变量。

示例代码:

public class ReadCheck {

    static BlockingQueue<A> queue = new LinkedBlockingQueue<>();

    public static class A {

        public int a;

        public A(int a) {
            this.a = a;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        A a = queue.take();
                        if (a.a != 20) {
                            System.out.println(a.a);
                        }
                    } catch (InterruptedException e) {
                    }
                }
            }
        }).start();


        while (true) {
            A a = new A(10);
            a.a = 20;
            queue.offer(a);
        }
    }
}

在示例运行期间,我从未看到变量为10(它总是20)。
在这种情况下,我是否可能读取了过期的变量值(10)?
这段代码示例是线程安全的吗?

英文:

I have a main thread which constructs an object with a non-volatile variable and then in this thread I change the value of the variable and put the object to BlockingQueue.
In second thread I wait until the object be available and read the object and its variable.

Example code:

public class ReadCheck {

    static BlockingQueue&lt;A&gt; queue = new LinkedBlockingQueue&lt;&gt;();

    public static class A {

        public int a;

        public A(int a) {
            this.a = a;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        A a = queue.take();
                        if (a.a != 20) {
                            System.out.println(a.a);
                        }
                    } catch (InterruptedException e) {
                    }
                }
            }
        }).start();


        while (true) {
            A a = new A(10);
            a.a = 20;
            queue.offer(a);
        }
    }
}

During run of example I've never seen that variable is 10 (it's always 20).
Is it possible that I read stale value (10) of variable in second thread in such case?
Is this code example thread safe?

答案1

得分: 2

不可以,你无法读取过期的值;是的,它将保证线程安全。

阻塞队列的保证offer操作发生在take操作之前,所以对A.a中的值的写操作将在你读取它之前发生。

> 与其他并发集合一样,在将对象放入阻塞队列之前的线程操作先于在另一个线程中访问或删除该元素之后的操作。

英文:

No, you can't read a stale value; yes, it will be thread safe.

The blocking queue guarantees that offer happens before take, so the write to the value in A.a will happen before you read it.

> As with other concurrent collections, actions in a thread prior to placing an object into a BlockingQueue happen-before actions subsequent to the access or removal of that element from the BlockingQueue in another thread.

huangapple
  • 本文由 发表于 2020年5月4日 14:43:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/61586528.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定