鍍金池/ 問(wèn)答/Java  Linux/ 對(duì)于代碼的線(xiàn)程安全問(wèn)題

對(duì)于代碼的線(xiàn)程安全問(wèn)題

import java.util.ArrayList;
import java.util.List;

public class Main {

    // ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
    int i;

    public void increment() {
        i++;
    }
    public static void main(String[] args) {

        Main main = new Main();
        
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                
                for (int i = 0; i < 10000; i++) {
                    main.increment();
                    System.out.println(main.i);
                }
            }
        };
        List<Thread> threads = new ArrayList<>(10);
        for (int i = 0; i < 3; i++) {
            Thread thread = new Thread(runnable);
            threads.add(thread);
            thread.start();
        }  
        boolean flag = false;
        while (!flag) {
            flag = true;
            for (Thread thread : threads) {
                if (thread.isAlive()) {
                    flag = false;
                }
            }

        }
        System.out.println(main.i);

    }
}

對(duì)于這個(gè)for循環(huán)中的System.out.println(main.i);
加上了這句話(huà)之后,每次輸出的結(jié)果都是30000,這是為什么

回答
編輯回答
歆久

不是線(xiàn)程安全是一定的,使用30,300個(gè)線(xiàn)程試試就知道了,讓你產(chǎn)生安全的錯(cuò)覺(jué)在System.out.println是一個(gè)耗時(shí)的同步方法,就是它在很大程度上掩蓋了i++的可見(jiàn)性和原子性的問(wèn)題。使用AtomicIntegersynchronized

2017年10月25日 04:37
編輯回答
挽歌
開(kāi)始以為是
public void println(int x) {
        synchronized (this) {
            print(x);
            newLine();
        }
}

后來(lái)發(fā)現(xiàn)我錯(cuò)了
方法本身的synchronized和被調(diào)用的方法的synchronized
確實(shí)是線(xiàn)程不安全的
跑300的結(jié)果
2999915
2018年5月10日 00:59