ThreadLocal和Synchronized区别

前言

  最近项目中使用到了ThreadLocal变量,所以学习了一下ThreadLocal以及与Synchronized的区别,并记录下来。

正文

  1、ThreadLocal变量的理解:

    使用ThreadLocal变量,当多个线程访问该变量时,都会为每个线程提供一个独立的变量副本,并且线程对该变量的操作实质是对自己变量副本的操作,不会对其它线程有影响。

 

  2、ThreadLocal和Synchronized的区别:

   (1)相同点:ThreadLocal和Synchronized都是为了解决多线程中访问相同变量的冲突问题。

   (2)不同点:

     ①、ThreadLocal:以空间换时间,为每个线程提供一个变量副本,消耗较多的内存,但是多个线程可以同时访问该变量而且相互不会影响。

     ②、Synchronized:以时间换空间,多个线程访问的是同一个变量,但是当多个线程同时访问该变量时,需要抢占锁,并且等待获取锁的线程释放锁,会消耗较多的时间。

 

  3、通过代码区别ThreadLocal和Synchronized:

   (1)普通的代码:

public class NormalTest implements Runnable{

    private Integer num = 0;

    private Integer addAndGetNum(){
        ++num;
        return num;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + addAndGetNum());
        }
    }

    public static void main(String[] args) {
        NormalTest normalTest = new NormalTest();
        new Thread(normalTest).start();
        new Thread(normalTest).start();
        new Thread(normalTest).start();

//        运行结果
//        Thread-1----2
//        Thread-1----3
//        Thread-0----1
//        Thread-2----1
//        Thread-0----4
//        Thread-2----5
//        Thread-2----7
//        Thread-0----6
    }
}

   (2)使用Synchronized代码:

public class SynchronizeTest implements Runnable{

    private Integer num = 0;

    private synchronized Integer addAndGetNum(){
        ++num;
        return num;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + addAndGetNum());
        }
    }

    public static void main(String[] args) {
        SynchronizeTest synchronizeTest = new SynchronizeTest();
        new Thread(synchronizeTest).start();
        new Thread(synchronizeTest).start();
        new Thread(synchronizeTest).start();

//    运行结果
//    Thread-1----2
//    Thread-2----3
//    Thread-0----1
//    Thread-0----6
//    Thread-2----5
//    Thread-1----4
//    Thread-2----8
//    Thread-0----7
//    Thread-1----9
    }
}

   (3)使用ThreadLocal代码:

public class ThreadLocalTest implements Runnable{

    private ThreadLocal<Integer> num = ThreadLocal.withInitial(()->0);

    private Integer addAndGetNum(){
        num.set(num.get() + 1);
        return num.get();
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + addAndGetNum());
        }
    }

    public static void main(String[] args) {
        ThreadLocalTest threadLocalTest = new ThreadLocalTest();
        new Thread(threadLocalTest).start();
        new Thread(threadLocalTest).start();
        new Thread(threadLocalTest).start();

//        运行结果
//        Thread-0----1
//        Thread-0----2
//        Thread-0----3
//        Thread-1----1
//        Thread-2----1
//        Thread-1----2
//        Thread-2----2
//        Thread-2----3
//        Thread-1----3
    }
}

 

posted @ 2020-09-27 18:38  路人甲、  阅读(456)  评论(0)    收藏  举报