0
点赞
收藏
分享

微信扫一扫

ThreadLocal里面的泛型不能是static修饰的变量 *

概念

当ThreadLocal里面存储的是static修饰的类或者变量也会出现线程不安全问题,因为在ThreadLocal里面持有的是对象的本身的引用,对于static变量而言,所有的类共享了static修饰的类或者变量的引用.

在ThreadLocal存放的是同一个对象的引用,所以多个线程看到的都是同一个对象的实例.所以ThreadLocal对static修饰的类或者变量不具备线程隔离.

解决办法

把static变量去掉,让它在每个线程都是独立的(在每个线程都单独new一个实例给ThreadLocal,这样就不会共享了.)

代码演示

static修饰了变量

import utils.SleepTools;

/**
* 类说明:ThreadLocal的线程不安全演示
* 多执行几次方法,看控制台输出,十个线程输出结果不全是 10 而且也没有做到线程隔离,这就是线程不安全的问题.
*/
public class ThreadLocalUnsafe implements Runnable {
//因为是static的,就被几个线程共享了,所以就产生了线程不安全的情况
public static Number number = new Number(0);

//把static去掉就正确了,让每个线程都拥有自己独立的number.此时十个线程的输出都是1
// public Number number = new Number(0);

@Override
public void run() {
//每个线程计数加一
number.setNum(number.getNum() + 1);
//将其存储到ThreadLocal中
value.set(number);
SleepTools.ms(2);
//输出num值
System.out.println(Thread.currentThread().getName() + "=" + value.get().getNum());
}

public static ThreadLocal<Number> value = new ThreadLocal<Number>() {
};

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

private static class Number {
public Number(int num) {
this.num = num;
}

private int num;

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

@Override
public String toString() {
return "Number [num=" + num + "]";
}
}

}

控制台打印结果

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

十个线程共享了这一个变量, 说明出现了线程安全问题

给static去掉

import utils.SleepTools;

/**
* 类说明:ThreadLocal的线程不安全演示
* 多执行几次方法,看控制台输出,十个线程输出结果不全是 10 而且也没有做到线程隔离,这就是线程不安全的问题.
*/
public class ThreadLocalUnsafe implements Runnable {
//因为是static的,就被几个线程共享了,所以就产生了线程不安全的情况
// public static Number number = new Number(0);

//把static去掉就正确了,让每个线程都拥有自己独立的number.此时十个线程的输出都是1
public Number number = new Number(0);

@Override
public void run() {
//每个线程计数加一
number.setNum(number.getNum() + 1);
//将其存储到ThreadLocal中
value.set(number);
SleepTools.ms(2);
//输出num值
System.out.println(Thread.currentThread().getName() + "=" + value.get().getNum());
}

public static ThreadLocal<Number> value = new ThreadLocal<Number>() {
};

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

private static class Number {
public Number(int num) {
this.num = num;
}

private int num;

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

@Override
public String toString() {
return "Number [num=" + num + "]";
}
}

}

控制台输出结果

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

可以看到10个线程都是用自己线程里面的变量,没有线程共享一个变量.


举报

相关推荐

0 条评论