Java线程学习笔记之线程安全与不安全

在JDK API,有很多类上面都写着是线程安全或者线程不安全,比如StringBuilder就是线程不安全的类,在多线程的情况下,如果需要同步,则建议使用StringBuffer。
存在成员变量的类用于多线程时是不安全的,不安全体现在这个成员变量可能发生非原子性的操作,而变量定义在方法内也就是局部变量是线程安全的。在日常开发中,通常需要考虑成员变量或者说全局变量在多线程环境下,是否会引发一些问题。以下是示例:
创建一个线程不安全的类:

public class Count {
    private int num;//成员变量
    public  void count() {
        for(int i=1;i<=10;i++){
            num+=i;
        }
        System.out.println("线程:"+Thread.currentThread().getName()+";数据:"+num);
    }
}

创建多线程并执行

public class ThreadSecurityTest {

    public static void main(String[] args){
        Runnable runnable = new Runnable() {
            Count count = new Count();
            @Override
            public void run() {
                count.count();
            }
        };
        for(int i=0;i<10;i++){
            new Thread(runnable).start();
        }
    }
}

这里,我们想要的结果是输出的值是一样的55
而实际上的输出结果是(会有不同的输出结果,反正不会是上面的):

线程:Thread-0;数据:55
线程:Thread-3;数据:165
线程:Thread-2;数据:275
线程:Thread-9;数据:495
线程:Thread-5;数据:550
线程:Thread-4;数据:220
线程:Thread-1;数据:165
线程:Thread-6;数据:330
线程:Thread-8;数据:440
线程:Thread-7;数据:385

完全乱掉,也就是说,所有的线程都在任意时刻读取和修改成员变量num的值,而且没有同步。也可以说这种错误是由于成员变量造成的
当我们把Count类的成员变量num变为方法变量的时候:

public class Count {
    //private int num;
    public synchronized void count() {
        int num = 0;
        for(int i=1;i<=10;i++){
            num+=i;
        }
        System.out.println("线程:"+Thread.currentThread().getName()+";数据:"+num);
    }
}

结果

线程:Thread-0;数据:55
线程:Thread-3;数据:55
线程:Thread-4;数据:55
线程:Thread-2;数据:55
线程:Thread-1;数据:55
线程:Thread-7;数据:55
线程:Thread-9;数据:55
线程:Thread-8;数据:55
线程:Thread-6;数据:55
线程:Thread-5;数据:55

或者我们把runnable的成员变量变为方法变量

线程:Thread-4;数据:55
线程:Thread-2;数据:55
线程:Thread-9;数据:55
线程:Thread-7;数据:55
线程:Thread-3;数据:55
线程:Thread-0;数据:55
线程:Thread-1;数据:55
线程:Thread-5;数据:55
线程:Thread-6;数据:55
线程:Thread-8;数据:55

输出都符合我们的预期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值