【问题标题】:volatile and synchronized with multiple thread doesn't work [duplicate]volatile 并与多线程同步不起作用[重复]
【发布时间】:2019-02-19 03:17:56
【问题描述】:
public class VolatileDemo implements Runnable{

private static volatile int count = 0;
private Random random = new Random();

public static void main(String[] args) {
    for(int i=0;i<1000;i++){
        new Thread(new VolatileDemo()).start();
    }
    while(Thread.activeCount()>1){
        Thread.yield();
    }
    System.out.println(count);
}

@Override
public synchronized void run() {
    try {
        Thread.sleep(random.nextInt(1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+" " + count++);
}

}

运行后(在jdk1.8),答案不是1000,请告诉我原因。

【问题讨论】:

  • 提示:尝试将该计数替换为类型 AtomicInteger 并调用该对象的相应方法。看看会发生什么。
  • 方法上同步意味着不能同时对同一个对象进行两次调用docs.oracle.com/javase/tutorial/essential/concurrency/…你可以尝试在for之外提取(new VolatileDemo)
  • @vmrvector。谢谢,我总是有点困惑。 @aigaoxiaode 如果你在静态对象上同步count++ 行,你会得到1000。
  • @SteveSmith,他在非静态方法run 上使用了synchronized 关键字。这意味着this(在他的例子中是VolatileDemo 实例)将用作监视器。而且当他创建多个VolatileDemo 实例时,监视器都是不同的,同步没有效果。带有private static final Object lockObject = new Object()synchronized(lockObject) {...} 块可以解决问题。 AtomicInteger 也可以。
  • @SteveSmith 感谢您的文档,但是如果我将活动线程的数量更改为 0,程序将永远不会停止,因为主线程仍然存在。

标签: java volatile


【解决方案1】:

Volatile 对于“增量”操作是不安全的,因为它不是原子的(读取、递增、写入) Volatile 只是保证对变量所做的更改将适用于所有读取它的线程。

对于安全增量操作,您应该改为使用“原子”变量

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 2013-08-10
    相关资源
    最近更新 更多