可能忽略的Java基础知识-小心使用synchronized和volatile

接着 一个三年Android开发的总结,一点点补充和完善,还是那句“希望对有一定Android开发基础的人进阶有裨益,倘若能让一些人少走些弯路,也算作是我做的一件有意义的事情。”

基本概念

1.并发编程需要理解几个特性:
(1)原子性:不会被打断或破坏的一个或一组操作,原子操作是不能被线程调度机制中断的操作
(2)可见性:写操作对所有的读操作都是立即可见的,例如一个线程中对变量的修改,其他线程读取到的是该变量最新修改后的值
(3)有序性:源代码的顺序与执行顺序的一致性

2.可重入函数:简单来说是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,而且可以多次重复执行此函数,而不必等先执行的部分执行完;
而不可重入的函数由于使用了一些共享资源,如成员变量或全局变量等,导致不可被打断或执行的结果会相互影响

3.synchronized:
java中的关键字,是以一个非null对象作为“锁”,对解决共享资源冲突提供了内置的支持,可用于
(1)修饰代码块,以synchronized(object){}的形式包围代码块,其作用的范围是大括号括起来的代码,锁住的是object,后续所有对同一object执行synchronized(object){}的代码都会等待;
(2)修饰成员函数,即同步方法,其作用的范围是整个方法,锁住的是改实例对象的this对象,后续该实例的所有同步方法都会等待;
(3)修饰静态方法,即同步静态方法,其作用的范围是整个静态方法,锁住的是类对应的Class对象,后续该类的所有静态方法都会等待。

4.volatile:
java中的关键字,修饰变量,确保可见性,但不保证原子性

常见误区

在多线程编程中往往由于疏忽,在使用synchronized和volatile时会出现以下一些情况:

  1. synchronized修饰一个类的多个成员函数,导致一个成员函数被调用时,其它成员函数的调用也被阻塞;典型的Android上的问题场景是,一个同步方法不耗时,可以被UI线程和子线程调用,而另一个同步方法耗时,被子线程调用,一旦子线程先执行同步方法,会导致UI线程阻塞
  2. 类似的synchronized修饰一个类的静态方法,那么该类的所有静态同步方法的执行,都会进行同步,特别容易出现在各种utils类中;
    上述两个问题,究其原因就是synchronized锁住的对象,前者是锁主的this对象,影响的是一个类的实例对象的所有成员函数;而后者锁住的是类的Class对象,影响的是该类声明的所有静态同步方法。解决方法可以单独声明一个对象,以synchronized(object){}的形式使用,也可以不用synchronized关键字,而是直接采用Lock的方法。

  3. 乱用volatile,误以为其具有原子性
    先看如下代码

private volatile int mCount;
    public void testFunc() {

        // create threads
        for (int i = 0; i < 2; i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int j = 0; j < 1000; j++) {
                        mCount++;
                    }
                }
            }).start();
        }

        try {
            Thread.sleep(1000);
            System.out.println("count value:" + mCount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

看看对mCount添加volatile修饰与否,testFunc函数多次执行的结果是否一致。可以发现最后输出mCount的值是不确定的,似乎是mCount的修改并没有对其它线程立即可见。但其实是自增操作的非原子性,即有读取mCount值,加1,存储mCount值三步。因此mCount++语句,用synchronized(object){}的形式包围即可

至于synchronized和volatile的具体使用和详细分析,可以看看下方的参考,非常详细:
1.Java并发编程:volatile关键字解析
2.Java 理论与实践: 正确使用 Volatile 变量
3.深入JVM锁机制1-synchronized

欢迎关注微信公众号“编程阳光”,你的关注是我持续的动力。转载请注明出处:http://blog.csdn.net/w7849516230

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值