局部变量一定线程安全吗

局部变量, 如果是基本类型或是包装类型, 依然不能通过多线程改变其值, 如果是对象, 则其属性值是线程不安全的

(对象引用是局部变量, 在栈内存, 但是对象本身还是处于堆内存)

这样理解还是有偏差, 如果是基础类型, 如int:

如果是全局变量, 那么各线程可以直接操作, 其一定是线程不安全的

如果是局部变量, 那么只能将该变量作为形参传入线程中, 这时int值是不能被改变的, 不管线程安全与否; 至于说一个对象引用传入

后对象中的属性可以被改变是因为对象存在于堆中, 对象引用作为形参传入只是让各形成能定位到这个对象, 既然是堆内存, 所以线程不安全


demo1:

public void compute(LocalDate date){

        //在切换租户时,只有当前线程的第一个租户id设置有效,或者说一个线程内无法切换数据源
        TenantContext.set("saas_base");
        List<TenantInfo> tenantInfoDtos = tenantInfoDao.getByStatus(1);
        CountDownLatch status = new CountDownLatch(tenantInfoDtos.size());
        tenantInfoDtos.forEach(x->threadPoolTaskExecutor.execute(new InnerThread(x.getTenantId(), date, status)));
        try {
            status.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info(date+":DailyDataReportTask执行完成");
    }

demo2: 输出为0

@Test
    public void textTask(){
        int i = 0;
        for(int j=0;j<10000;j++){
        pool.execute(new InnerThread(i));}
        try {
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(i);
    }

    class InnerThread implements Runnable{
        public int i;
        public InnerThread(int i){
            this.i=i;
        }
        public void run(){
            i=i+1;
        }
    }

demo3 输出9963

@Setter
@Getter
@AllArgsConstructor
public class Testsss {

    int i;

}
  @Test
    public void textTask(){
        Testsss t = new Testsss(0);
        for(int j=0;j<10000;j++){
        pool.execute(new InnerThread(t));}
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getI());
    }

    class InnerThread implements Runnable{
        public Testsss t;
        public InnerThread(Testsss t){
            this.t=t;
        }
        public void run(){
            t.setI(t.getI()+1);
        }
    }

demo4: 输出10000

    @Test
    public void textTask() {
        Testsss t = new Testsss(0);
        for (int j = 0; j < 10000; j++) {
            pool.execute(new InnerThread(t));
        }
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getI());
    }

    class InnerThread implements Runnable {
        public Testsss t;

        public InnerThread(Testsss t) {

            this.t = t;
        }

        public void run() {
            synchronized (t) {
                t.setI(t.getI() + 1);
            }

        }
    }

 

posted @ 2018-07-16 15:46  車輪の唄  阅读(44)  评论(0)    收藏  举报  来源