java多线程累加 第一次累加出现重复

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Start implements Runnable {
    protected int count = 0;

    @Override
    public void run() {
        while (count < 100) {
            count++;
            System.out.println(Thread.currentThread().getName() + " count:" + count);
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new Start();
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 2; i++) {
            executorService.execute(runnable);
        }
        executorService.shutdown();
    }
}

第一次累加会重复,如果加锁就是顺序输出基本都是一个线程干活了,是不是我代码第一次读写的有问题。。。

阅读 5k
4 个回答

加锁你看到基本只是一个线程干活,是因为次数太少。提高到10000或者更多,就可以看到区别了

while (count < 10000) {
    synchronized (this) {
        count++;
        System.out.println(Thread.currentThread().getName() + " count:" + count);
    }
}

count++本身非线程安全,加锁(如上)或者使用AtomicInteger.

补充一点,
使用volatile修饰并不能解决count++不是线程安全的问题。关于自增操作的线程安全性可以看这篇文章 ++操作的线程安全性及相关问题

  1. 多线程的实现有问题,为什么是同一个Runnable对象被提交三次,如果希望多个线程并发修改一个值,应该把count声明为静态的全局变量,并且新建多个Runnable任务来并发运行。
  2. count++不是原子性操作,肯定会出现问题。建议使用AtomicInteger类型来控制并发

count非线程安全,参考原子操作类,或synchronized的用法

count++;这个操作会先读取线程本地内存中的count值,再去进行++操作,最后同步到主内存。所以就会出现以下问题:

线程1:读取本地count = 0;
线程2:读取本地count = 0;
线程1:count++;刷新到主内存 count = 1;
线程2:count++;刷新到主内存 count = 1;

解决方法

1、使用AtomicInteger代替int,保证变量原子性;
2、加锁
推荐问题