线程安全
如果一个类在单线程环境下正常运行,在多线程环境下也能正常运行,则称为线程安全。
Java类库中的ArrayList,HashMap和SimpleDateFormat都是非线程安全的。
原子性
类似于数据库的原子性,此处不再赘述。
实现原子性的方式有两种:一是使用锁,保证同一时刻只能被一个线程访问;二是使用CAS,可以理解为硬件层面上的锁。
Java语言中,long和double型以外的任何类型的变量的写操作都是原子操作。尽量如此,使用volatile关键字修饰的long/double型变量的写操作具有原子性。volatile关键字仅能保证变量写操作的原子性。
方法如果使用synchronized关键字进行修饰后,这个方法在任一时刻只能被一个线程执行,使得这个方法具有原子性。
可见性
如果一个线程对某个共享变量更新后,其他线程访问该变量读取到的值是新的值,就称线程对该变量的更新对其他线程具有可见性。导致不可见的原因涉及到JIT编译器,寄存器,缓冲区,内存等内容,不是很懂,就不详细说了。
要保证可见性,只需要定义变量的时候加上关键字volatile,例如:
private volatile boolean a = false;
- Java语言规范保证,父线程在启动子线程之前对共享变量的更新对于子线程来说是可见的。
例如:
1. x=0;
2. 在内部设置变量x=1;
3. 启动子线程,读取x;
4. 启动子线程后,设置x=2;
结果,子线程读出来的x可能为1,也可能为2。如果把3和4对调一下,那么子线程读出来的就是更新后的结果。
- Java语言规范保证,一个线程终止后该线程对共享变量的更新对于调用该线程的join方法的线程是可见的。例如:
1. x=0;
2. 启动子线程a,在子线程内部设置x=1;
3. 使用a.join()方法等待子线程结束。
4. 子线程结束后,读x值。
结果,读出来的值x=1。
网友评论