欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

7.1 什么是线程安全的类,实现线程安全对象的常用方法总结

程序员文章站 2022-04-29 10:40:24
在《Java并发编程实战》中,定义如下:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。实现线程安全的类常用方式线程封闭把对象封装到线程中,只有这个线程能够看到此对象无状态的类没有任何成员变量的类让类不可变1、加final关键字2、不提供修改成员变量,也不提供获取成员变量方法使用volatile...

目录

 

1、在《Java并发编程实战》中,定义如下:

2、实现线程安全的类常用方式

2.1线程封闭:把对象封装到线程中,只有这个线程能够看到此对象

2.2无状态的类:没有任何成员变量的类

2.3 让类不可变

2.3.1 加final关键字

2.3.2不提供修改成员变量,也不提供获取成员变量方法

2.4 volatile

2.5 加锁和CAS

2.6 安全的发布类:8个基本数据类型:int\short\char\byte\float\double\boolean\long

2.7 使用ThreadLocal

3 为什么servlet不是线程安全的类


1、在《Java并发编程实战》中,定义如下:

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

2、实现线程安全的类常用方式

线程封闭 把对象封装到线程中,只有这个线程能够看到此对象
无状态的类 没有任何成员变量的类
让类不可变

1、加final关键字

2、不提供修改成员变量,也不提供获取成员变量方法

使用volatile 保证类的可见性,不能保证线程安全。适合一写多读的场景
加锁和CAS 使用synchronized、lock、原子变量AtomicInteger等
安全的发布

如果类中有基本类型成员变量,发布出去其实是变量的副本,不是引用

int、short、char、byte、float、double、boolean、long

ThreadLocal 每个线程自己维护了一个ThreadLocalMap

2.1线程封闭:把对象封装到线程中,只有这个线程能够看到此对象

2.2无状态的类:没有任何成员变量的类

/**
 * 无状态的类:没有任何变量
 */
public class Test{
	public int add(int a,int b){

	    return a+b;
    }

    public void test(UserVo user){

    }
}

2.3 让类不可变

2.3.1 加final关键字

/**
 * 类变量不能被修改,只能获取
 **/
public class Test1 {
     private final String name;
     private final Integer age;

    public Test1(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

2.3.2不提供修改成员变量,也不提供获取成员变量方法

/**
 * 没有获取值、修改值的方法,所以是线程安全的
 **/
public class Test2 {
    private Integer[] a = new Integer[]{1,2,3};
    
    public boolean testContain(int b){
        return Arrays.asList(a).contains(b);
    }
}

2.4 volatile

2.5 加锁和CAS

使用synchronized、lock、原子变量AtomicInteger等

2.6 安全的发布类:8个基本数据类型:int\short\char\byte\float\double\boolean\long

/**
 * 基本数据类型,在每个线程中会是一个副本
 **/
public class Test3 {
    private int a;
    private boolean b;
    private byte c;
    private float d;
    private double e;
    private short f;
    private char g;
    private long h;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public static void main(String[] args) {
        Test3 test3 = new Test3();
        test3.setA(1);
        System.out.println(test3.getA());
    }
}

2.7 使用ThreadLocal

3 为什么servlet不是线程安全的类

servlet不是线程安全的类,我们平时用却没有考虑多线程?

1、很少有需要共享servlet的需求

2、从接受请求到返回应答,基本都是由一个线程来完成的

但是还是要警惕,如果servlet中有成员变量,不做好控制,很可能会发生线程安全问题

 

本文地址:https://blog.csdn.net/qq_22701869/article/details/107271921