线程独自拥有一个局部变量,需要在应用层上保证每一个线程有不同的对象,ThreadLocal起到了容器的作用
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyObject {
String name;
MyObject(String name) {
this.name = name;
}
@Override
public String toString() {
return "MyObject{" + "name='" + name + '\'' + '}';
}
}
public class ThreadLocalTest {
static ThreadLocal object = new ThreadLocal<>();
static class MyThread extends Thread {
@Override
public void run() {
if (object.get() == null) {
object.set(new MyObject("test"));
}
System.out.println(object.get());
}
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
service.submit(new MyThread());
}
}
}
将数据写入线程持有的ThreadLocalMap ,键-值=对象-当前值
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
获取线程的ThreadLocalMap,再将自己作为键,获取对应的值
/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
将对象设置在ThreadLocal中,其实是设置在线程的ThreadLocalMap 中,如果对象没有及时得到清理,那么他将无法回收,造成内存泄露
/**
* Removes the current thread's value for this thread-local
* variable. If this thread-local variable is subsequently
* {@linkplain #get read} by the current thread, its value will be
* reinitialized by invoking its {@link #initialValue} method,
* unless its value is {@linkplain #set set} by the current thread
* in the interim. This may result in multiple invocations of the
* {@code initialValue} method in the current thread.
*
* @since 1.5
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
手动设置ThreadLocal=null,回收所有变量
static class Entry extends WeakReference> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);
value = v;
}
}
当ThreadLocal设为null时,键为空,则当系统对ThreadLocalMap 进行清理时,就会回收所有失效的(弱)键值对
是一种乐观策略,假设对资源的访问时没有冲突的,所有线程都不会被阻塞
CAS(V,E,N)
仅当V=E时,V的值才会设为N。如果V≠E,说明已经有其他线程修改了,可以再尝试修改。最后CAS返回V的真实值
执行类中的指令时,不会被其他线程打断,直接使用CAS操作
保证安全的整数操作
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicTest {
static AtomicInteger integer = new AtomicInteger();
static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
integer.incrementAndGet();
}
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
thread.join();
}
System.out.println(integer);
}
}
//当前实际值
private volatile int value;
//实际值的偏移量
private static final long valueOffset;
//委托给非安全的指针操作
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
//CAS操作+本地方法
//不断重试,直到对象的当前值var5和偏移量var2相同,CAS操作成功,将结果赋值给var2
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
保证修改对象引用的安全性,但是不能确保对象引用不被修改
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class AtomicTest {
static AtomicInteger integer = new AtomicInteger();
static AtomicReference reference = new AtomicReference<>();
static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
// integer.incrementAndGet();
Integer m = reference.get();
reference.compareAndSet(m,m+1);
}
}
}
public static void main(String[] args) throws InterruptedException {
reference.set(0);
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
thread.join();
}
// System.out.println(integer);
System.out.println(reference.get());
}
}
带有时间戳的对象引用,在内部不仅维护了对象值,也维护了对象的状态值。当对象被修改时,需要同时修改数据和时间戳。当要修改对象时,需要数据和时间戳都满足期望值
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
public class AtomicTest {
// static AtomicInteger integer = new AtomicInteger();
// static AtomicReference reference = new AtomicReference<>();
static AtomicStampedReference reference = new AtomicStampedReference<>(0,0);
static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
// integer.incrementAndGet();
Integer m = reference.getReference();
final int stamp = reference.getStamp();
reference.compareAndSet(m,m+1,stamp,stamp+1);
}
}
}
public static void main(String[] args) throws InterruptedException {
// reference.set(0);
reference.set(0,0);
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
thread.join();
}
// System.out.println(integer);
System.out.println(reference.getReference()+" "+reference.getStamp());
}
}
通过CAS方式,控制数组的安全性
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
public class AtomicTest {
// static AtomicInteger integer = new AtomicInteger();
// static AtomicReference reference = new AtomicReference<>();
static AtomicIntegerArray array = new AtomicIntegerArray(10);
// static AtomicStampedReference reference = new AtomicStampedReference<>(0,0);
static class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// integer.incrementAndGet();
// Integer m = reference.getReference();
// final int stamp = reference.getStamp();
// reference.compareAndSet(m,m+1,stamp,stamp+1);
array.getAndIncrement(i);
}
}
}
public static void main(String[] args) throws InterruptedException {
// reference.set(0);
// reference.set(0,0);
for (int i = 0; i < 10; i++) {
MyThread thread = new MyThread();
thread.start();
thread.join();
}
// System.out.println(integer);
// System.out.println(reference.getReference()+" "+reference.getStamp());
System.out.println(array);
}
}
普通变量也可以进行CAS操作,只能修改可见的、volatile类型的变量,不支持static类型
import java.util.concurrent.atomic.*;
public class AtomicTest {
// static AtomicInteger integer = new AtomicInteger();
// static AtomicReference reference = new AtomicReference<>();
// static AtomicIntegerArray array = new AtomicIntegerArray(10);
// static AtomicStampedReference reference = new AtomicStampedReference<>(0,0);
static class MyField {
volatile int data;
}
static AtomicIntegerFieldUpdater updater = AtomicIntegerFieldUpdater.newUpdater(MyField.class,"data");
static class MyThread extends Thread{
private MyField field;
public MyThread(MyField field) {
this.field = field;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
// integer.incrementAndGet();
// Integer m = reference.getReference();
// final int stamp = reference.getStamp();
// reference.compareAndSet(m,m+1,stamp,stamp+1);
// array.getAndIncrement(i);
updater.incrementAndGet(field);
}
}
}
public static void main(String[] args) throws InterruptedException {
// reference.set(0);
// reference.set(0,0);
MyField field = new MyField();
for (int i = 0; i < 10; i++) {
// MyThread thread = new MyThread();
MyThread thread = new MyThread(field);
thread.start();
thread.join();
}
// System.out.println(integer);
// System.out.println(reference.getReference()+" "+reference.getStamp());
// System.out.println(array);
System.out.println(field.data);
}
}