对Java线程安全与不安全的理解

2018-07-30  本文已影响0人  kindol

一个线程不安全的类

public class Count {  
    private int num;  
    public void count() {  
        for(int i = 1; i <= 10; i++) {  
            num += i;  
        }  
        System.out.println(Thread.currentThread().getName() + "-" + num);  
    }  
}  

正常的理解,调用count()应该会输出55

在主函数中启动10个线程:

public class ThreadTest {  
    public static void main(String[] args) {  
        Runnable runnable = new Runnable() {  
            Count count = new Count();  
            public void run() {  
                count.count();  
            }  
        };  

        for(int i = 0; i < 10; i++) {  
            new Thread(runnable).start();  
        }  
    }  
}  

输出结果如下:

Thread-0-55  
Thread-1-110  
Thread-2-165  
Thread-4-220  
Thread-5-275  
Thread-6-330  
Thread-3-385  
Thread-7-440  
Thread-8-495  
Thread-9-550

只有Thread-0线程输出的结果是我们期望的,其他的跟想象中的不符,为何?

每个线程都有自己的工作内存(线程栈),工作内存存储了主内存count对象的一个副本,当线程操作count对象时,首先从主内存复制count对象到工作内存中,然后执行代码count.count(),改变了num值,最后用工作内存中的count刷新主内存的 count

可以看出,多个线程对同一个实例类的同一个变量操作是不安全的,不安全体现在这个成员变量可能发生非原子性的操作,然而,变量定义在方法内(局部变量)、多个线程访问同一个对象中的同步方法是安全的

java线程的两个特性:可见性(也就是工作内存会刷新主内存)、有序性(结果取决于线程调度的精准时序)

上一篇下一篇

猜你喜欢

热点阅读