课程素材来自 http://enjoy.ke.qq.com/ 版权所有
什么是线程安全
如果多个线程访问并使用这个类,这类总是表现线程安全的,那么这个类就是线程安全的。
类的线程安全表现为:
l 操作的原子性
l 内存的可见性
不做正确的同步,在多个线程之间共享状态的时候,就会出现线程不安全。
怎么做到线程安全
栈封闭
所有的变量都在方法内部声明的,这些状态都处于栈封闭状态。
示例代码:
无状态的类
没有任何成员变量的类,就叫无状态的类
package com.hw.ch9; public class Stateless { public String result() { return "success"; } } 让类不可变
让状态不可变,两种方式:
1,加final关键字,对于一个类,所有的成员变量应该是私有的,同样的只要有可能,所有的成员变量应该加上final关键字,
但是加上final,要注意如果成员变量又是一个对象时,这个对象所对应的类也要是不可变,才能保证整个类是不可变的。
public class ImmutableFinal { private final int a; private final int b; public ImmutableFinal(int a, int b){ this.a=a; this.b=b; } public int getA() { return a; } public int getB() { return b; } }
2、根本就不提供任何可供修改成员变量的地方,同时成员变量也不作为方法的返回值
public class ImmutableFinalRef { private final int a; private final int b; private final User user; public ImmutableFinalRef(int a, int b,User user){ this.a=a; this.b=b; this.user = user; } public int getA() { return a; } public int getB() { return b; } public static class User{ private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } }这样的也是不安全的操作,因为别个的线程可以获取到user对象的引用,可以改变user的值,但是,把
user对象的代码改成这样
public class User{ // private int age; private final int age; public User(int age){ this.age = age; } public int getAge() { return age; } // public void setAge(int age) { // this.age = age; // } }线程就安全了,因为没有修改的方法了。
volalite
保证类的可见性,最适合一个线程写,多个线程读的情景
加锁和cas
安全的发布
类中持有的成员变量,特别是对象的引用,如果这个成员对象不是线程安全的,
通过get等方法发布出去,会造成这个成员对象本身持有的数据在多线程下不正确的
修改,从而造成整个类线程不安全的问题。
ThreadLocal
多个线程变量安全