并发编程 ThreadLocal

2019-02-13  本文已影响2人  黄靠谱

概述

1个对象被多个线程同时引用且操作(比如作为线程的成员变量),会引发线程安全的问题。但是可以通过给该对象设置ThreadLocal属性,来实现一个对象在不同线程里面,同时操作ThreadLocal属性时,相互隔离的效果。

使用示范

为了解决公用变量不安全的情况,可以通过ThreadLocal来定义某些变量为线程独有的,从而实现线程隔离

例如下面的,对线程私有变量 number进行threadlocal处理,对于公用变量 sharedNumber不做处理,实现线程共享传递参数

public class SeqCount {
        private static ThreadLocal<Integer> number = new ThreadLocal<Integer>(){
            public Integer initialValue() {
                return 0;
            }
        };
        int sharedNumber=0;
        public int nextSeq(){
            number.set(number.get() + 1);

            return number.get();
        }

        public static void main(String[] args){
            SeqCount seqCount = new SeqCount();
            for(int i=0;i<4;i++){
                 new SeqThread(seqCount).start();
            }
        }

        private static class SeqThread extends Thread{
            private SeqCount seqCount;

            SeqThread(SeqCount seqCount){
                this.seqCount = seqCount;
            }

            public void run() {
                for(int i = 0 ; i < 3 ; i++){
                    System.out.println(Thread.currentThread().getName() + " seqCount :" + seqCount.nextSeq());
                    
                    seqCount.sharedNumber++;
                    System.out.println(Thread.currentThread().getName() + " shareNumber :" + seqCount.sharedNumber);
                }
            }
        }
}

ThreadLocal实现线程隔离原理:

每个Thread独立拥有一个ThreadLocalMap,实现线程之间变量的隔壁,然后set、get都是对这个ThreadLocalMap进行操作,其中的key就是申明的ThreadLocal,线性探测法实现的HashMap的数据结构

Thread :每个Thread只有一个独立绑定的ThreadLocalMap,线程独享
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);

ThreadLocalMap:每个ThreadLocalMap拥有一个线性探测的HashMap结构,每个Entry的key就是一个ThreadLocal
    private Entry getEntry(ThreadLocal key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
     }

ThreadLocal : 每个Thread可以定义多个ThreadLocal

        private static ThreadLocal<Integer> number = new ThreadLocal<Integer>(){
            public Integer initialValue() {
                return 0;
            }
        };
        
        private static ThreadLocal<Integer> number2 = new ThreadLocal<Integer>(){
            public Integer initialValue() {
                return 1;
            }
        };
上一篇 下一篇

猜你喜欢

热点阅读