前言
初入开发的靓仔会有前辈告诉你在并发编程中需要维持线程安全,
那么到底什么是线程安全?
有个叫 Brian Goetz的靓仔说过,
他是《Java Concurrency In Practice》的作者,
中文翻译:《Java并发编程实战》
当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行问题,也不需要进行额外的同步,而调用这个对象的行为都可以获得正确的结果,那这个对象便是线程安全的。
简单理解就是
正确的结果等于安全
或者你可以为线程安全需要的三种特性:原子性,可见性,有序性就是代表线程安全。
原子性
最简单的一种情况你小时候想买串糖葫芦吃,付了钱。
可是那个卖糖葫芦的老头却不给你糖葫芦,
最后你钱货两失,奇惨无比。
还有现实生活的转账,你转了钱别人没收到。
因此这些行为需要保持一个特性,
我们称之为原子性:即操作要么全部执行成功,要么就都不执行。
保持这种特性是线程安全的一个必要,
可见性
除此之外还有可见性,
指多个线程访问同一个变量时,假设一个线程修改了这个变量的值,其它线程可以立马看到修改后的值。
最常见的例子是大促销时你天猫,京东买东西,
提交了订单却被告知没有库存,无法购买。
出现这种问题的原因是:
在你下单的时候,有位土豪已经买了下所有商品而你看到的剩余库存其实已经清零。
有序性
即程序执行的顺序按照代码的先后顺序。
例如线程执行就不是依照代码的先后顺序执行,
public static void main(String[] args) {
MyRunnable1 runnable1 = new MyRunnable1();
MyRunnable2 runnable2 = new MyRunnable2();
MyRunnable3 runnable3 = new MyRunnable3();
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
Thread thread3 = new Thread(runnable3);
thread1.start();
thread2.start();
thread3.start();
}
public static class MyRunnable1 implements Runnable{
@Override
public void run(){
System.out.println("开启线程1");
}
}
public static class MyRunnable2 implements Runnable{
@Override
public void run(){
System.out.println("开启线程2");
}
}
public static class MyRunnable3 implements Runnable{
@Override
public void run(){
System.out.println("开启线程3");
}
}
执行结果:
开启线程3
开启线程1
开启线程2
再次执行
开启线程1
开启线程2
开启线程3