当前位置: 首页 > 面试题库 >

说明volatile:此代码是线程安全的吗?

皇甫德庸
2023-03-14
问题内容

我试图volatile用一个例子来说明它的使用和重要性,如果volatile省略的话,它实际上不会给出很好的结果。

但我并不习惯使用volatile。下面的代码的想法是,如果volatile省略则导致无限循环,如果存在则是完全线程安全的volatile。以下代码是线程安全的吗?您是否还有其他使用的现实且简短的代码示例,如果没有该示例volatile将会给出明显不正确的结果?

这是代码:

public class VolatileTest implements Runnable {

    private int count;
    private volatile boolean stopped;

    @Override
    public void run() {
        while (!stopped) {
            count++;
        }
        System.out.println("Count 1 = " + count);
    }

    public void stopCounting() {
        stopped = true;
    }

    public int getCount() {
        if (!stopped) {
            throw new IllegalStateException("not stopped yet.");
        }
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileTest vt = new VolatileTest();
        Thread t = new Thread(vt);
        t.start();
        Thread.sleep(1000L);
        vt.stopCounting();
        System.out.println("Count 2 = " + vt.getCount());
    }
}

问题答案:

Victor是对的,您的代码存在问题:原子性和可见性。

这是我的版本:

    private int count;
    private volatile boolean stop;
    private volatile boolean stopped;

    @Override
    public void run() {
        while (!stop) {
            count++; // the work
        }
        stopped = true;
        System.out.println("Count 1 = " + count);
    }

    public void stopCounting() {
        stop = true;
        while(!stopped)
           ; //busy wait; ok in this example
    }

    public int getCount() {
        if (!stopped) {
            throw new IllegalStateException("not stopped yet.");
        }
        return count;
    }

}

如果线程观察到stopped==true,则可以确保工作完成并且结果可见。

从易失性写入到易失性读取(在同一变量上)之间存在事前关系,因此如果有两个线程

   thread 1              thread 2

   action A
       |
 volatile write  
                  \
                     volatile read
                          |  
                       action B

动作A在动作B之前发生;B中可以看到A中的写入。



 类似资料:
  • 我试图理解如果下面是线程安全的,它是由另一个开发人员编写的代码,我已经继承和不再与我们在一起。 我有一个BaseProvider类,它实际上是一个消息缓存,由LinkedBlockingQueue表示。该类将传入的消息存储在队列中。 我有一组读此队列的辅助线程。因此,LinkedBlockingQueue是线程安全的。 正如您所注意到的,每个辅助线程都可以访问所有的提供者,所以当一个辅助线程遍历所

  • 问题内容: Java线程安全性易变吗?也就是说,可以安全地读取和写入它而无需锁定吗? 问题答案: 是的,您可以从中读取并安全地对其进行写入-但您不能做任何复合操作,例如安全地对其进行递增,因为这是一个读/修改/写周期。还有一个问题是它如何与 其他 变量的访问交互。 坦率地说,volatile的确切性质令人困惑(有关更多详细信息,请参见JLS的内存模型部分)-我 个人 通常会使用它作为确保正确使用的

  • 问题内容: 很简单,可以从多个线程中使用一个实例(例如),还是需要将多个实例放在一个线程中? 问题答案: 不,不是。该实例是有状态的。因此,您需要将其存储在threadlocal中,或者在每次加密/解密调用中获取一个新实例,或者将其包装在一个块中。 Threadsafety通常在Javadoc中提到“ 是线程安全的 ”或“ 是 不是 线程安全的 ”。情况并非如此,因此您不应假定它是线程安全的。

  • 类OneValueCache是不可变的。但是我们可以更改变量缓存的引用。 但我不能理解为什么VolateCachedFactorizer类是线程安全的。 对于两个线程(线程A和线程B),如果线程A和线程B同时到达,那么两个线程A和B都将尝试创建OnEvalueCache。然后线程A到达而线程B同时到达。然后线程A将创建一个,它覆盖threadB创建的值(OneValueChange是不可变的,但是

  • 功能简介 一键报警 一键报警是在不方便语音通话的场景下,求助人无需进行复杂的信息编辑,可由平台提供更准确的实时定位信息、求助人和同车人信息和音视频信息供警方使用。 具体参见:一键报警 行程分享 行程分享是乘车人可以将当前行程分享到微信、短信、QQ、微博、钉钉等任意渠道中,让亲友随时关注行程信息。 具体参见:行程分享 紧急联系人 紧急联系人是乘车人在遇到紧急情况时向其发起帮助请求的人,设置后,可开启

  • volatile的写操作,无法保证线程安全。例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1对count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。