1. 程式人生 > >區域性變數一定執行緒安全嗎

區域性變數一定執行緒安全嗎

區域性變數, 如果是基本型別或是包裝型別, 依然不能通過多執行緒改變其值, 如果是物件, 則其屬性值是執行緒不安全的

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);
            }

        }
    }