美文网首页
JAVA多线程变量的线程安全问题

JAVA多线程变量的线程安全问题

作者: 阡陌笙箫 | 来源:发表于2020-06-02 14:55 被阅读0次

当使用Thread线程时候,在线程内打印this.getName(线程名称)时,默认返回递增的Thread-i,就此产生了疑问,为何new Thread()对象,但是线程号确实递增的。
测试代码:

for(int i=0;i<10;i++){
    Thread t = new Thread();
    System.out.println(t.getName()); //名字自增
}

打印结果:

Thread-0
Thread-1
Thread-2
Thread-3
Thread-4
Thread-5
Thread-6
Thread-7
Thread-8
Thread-9

Thread源码部分:

//无参构造方法
public Thread(){
    init(null, null, "Thread-" + nextThreadNum(), 0L);
}

//自增线程号
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}

由此可见:Thread内部使用static修饰了线程号变量,并且在获取线程号方法上面加了锁,这样即使多线程同时访问,线程是安全的。即线程号是递增的。

总结

  1. 静态变量(static int number)
  2. 静态对象(static Object bean)
  3. 局部变量(int number)
  4. 局部对象(Object bean)

静态变量/对象:
被static修饰的成员变量和成员方法独立于该类的任何对象, 类的所有实例共享同一个static变量
静态变量也称为类变量,属于类对象所有,位于方法区,为所有对象共享,共享一份内存,一旦值被修改,则其他对象均对修改可见,故线程非安全。

局部变量/对象:
线程安全, 每个线程执行时都会把局部变量放在各自的帧栈的内存空间中,线程间不共享,故不存在线程安全问题。
对象如果是单例,也是线程不安全的。

  1. 静态变量
public class Thread2 extends Thread{
    //static 静态常量
    private static int threadInitNumber;
    
    public Thread2(int i){
        Thread2.threadInitNumber = i;
    }
    @Override
    public void run() {
                //打印静态变量
        System.out.println("Thread-"+ threadInitNumber);
    }

    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Thread2 t = new Thread2(i);
            t.start();
        }
    }
}

输出结果:静态变量被串改了,线程不安全

Thread-2
Thread-4
Thread-4
Thread-2
Thread-5
Thread-8
Thread-8
Thread-9
Thread-9
Thread-9
  1. 静态对象
public class Thread3 extends Thread{
    //static 静态对象
    private static Bean bean;
    
    public Thread3(Bean bean){
        Thread3.bean = bean;
    }
    @Override
    public void run() {
        System.out.println("Thread-"+ bean.getId()+"---"+bean);
    }
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Bean bean = new Bean(i); //每次都初始化一个新的实体Bean
            Thread3 t = new Thread3(bean);
            t.start();
        }
    }
}
/**定义一个测试实体类*/
class Bean {
    int id;
    public Bean(int id){
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Bean [id=" + id + "]";
    }
}

输出结果:对象Bean属性id也被串改了,线程不安全

Thread-2---Bean [id=2]
Thread-4---Bean [id=4]
Thread-3---Bean [id=3]
Thread-2---Bean [id=2]
Thread-6---Bean [id=6]
Thread-8---Bean [id=8]
Thread-8---Bean [id=8]
Thread-9---Bean [id=9]
Thread-9---Bean [id=9]
Thread-9---Bean [id=9]
  1. 局部变量:把static去掉
public class Thread4 extends Thread{
    private int threadInitNumber;
    private int nextThreadNum(){
        int newNumber = threadInitNumber++;
        return newNumber;
    }
    public void run(){
        System.out.println("Thread-"+ nextThreadNum());
    }
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Thread4 t = new Thread4();
            t.start();
        }
    }
}

输出结果:变量没有被串改,都是从0开始的,线程安全

Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
  1. 局部对象
public class Thread5 extends Thread{
    private Bean bean;
    public Thread5(Bean bean){
        this.bean = bean;
    }
    public void run(){
        System.out.println("Thread-"+ bean.getId()+"---"+bean);
    }   
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            Bean bean = new Bean(i);
            Thread5 t = new Thread5(bean);
            t.start();
        }
    }
}

输出结果:对象私有,不共享,线程安全

Thread-0---Bean [id=0]
Thread-2---Bean [id=2]
Thread-1---Bean [id=1]
Thread-3---Bean [id=3]
Thread-4---Bean [id=4]
Thread-5---Bean [id=5]
Thread-6---Bean [id=6]
Thread-7---Bean [id=7]
Thread-9---Bean [id=9]
Thread-8---Bean [id=8]

相关文章

  • volatile关键字

    线程安全问题 Java多线程带来的一个问题是数据安全问题,判断一段Java代码是否有线程安全问题可从以下几点入手:...

  • 多线程之ThreadLocal

    ThreadLocal threadLocal是用来解决多线程并发访问的线程安全问题,其实就是把变量隔离在线程内部...

  • JAVA多线程变量的线程安全问题

    当使用Thread线程时候,在线程内打印this.getName(线程名称)时,默认返回递增的Thread-i,就...

  • java多线程(壹)——线程与锁

    线程与线程安全问题 所有的线程安全问题都可以概况为三个点:原子性,可见性、有序性——————by Java多线程编...

  • java多线程安全问题

    Java 每次请求controller都是唯一的拦截器也是唯一的不同方法间共享的变量会存在多线程安全问题 并发请求...

  • java多线程相关笔记

    变量空间开辟条件: 变量的作用域 数据类型 java内存 多线程 1.线程和进程 2.多线程的作用 随着工业的进步...

  • 1-引入synchronized锁

    引入 线程安全问题 在java的多线程的编程中,经常出现线程安全的问题,主要就在于正确性:即多线程对临界资源进行访...

  • 关于AtomicInteger

    AtomicInteger JAVA原子操作的Interger类, 主要为解决多线程线程安全问题,今天拿来测试一下...

  • JAVA 多线程与锁

    JAVA 多线程与锁 线程与线程池 线程安全可能出现的场景 共享变量资源多线程间的操作。 依赖时序的操作。 不同数...

  • 京东资深架构师推荐学习6本实战文档:Redis+Nginx+My

    Java多线程编程核心技术_完整版 第1章 Java多线程技能 第2章 对象及变量的并发访问 第3章 线程间通信 ...

网友评论

      本文标题:JAVA多线程变量的线程安全问题

      本文链接:https://www.haomeiwen.com/subject/actuzhtx.html