可能忽略的Java基础知识-小心使用synchronized和volatile
基本概念1.并发编程需要理解几个特性:(1)原子性:不会被打断或破坏的一个或一组操作,原子操作是不能被线程调度机制中断的操作(2)可见性:写操作对所有的读操作都是立即可见的,例如一个线程中对变量的修改,其他线程读取到的是该变量最新修改后的值(3)有序性:源代码的顺序与执行顺序的一致性2.可重入函数:简单来说是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,而且可以多次重复
接着 一个三年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时会出现以下一些情况:
- synchronized修饰一个类的多个成员函数,导致一个成员函数被调用时,其它成员函数的调用也被阻塞;典型的Android上的问题场景是,一个同步方法不耗时,可以被UI线程和子线程调用,而另一个同步方法耗时,被子线程调用,一旦子线程先执行同步方法,会导致UI线程阻塞
类似的synchronized修饰一个类的静态方法,那么该类的所有静态同步方法的执行,都会进行同步,特别容易出现在各种utils类中;
上述两个问题,究其原因就是synchronized锁住的对象,前者是锁主的this对象,影响的是一个类的实例对象的所有成员函数;而后者锁住的是类的Class对象,影响的是该类声明的所有静态同步方法。解决方法可以单独声明一个对象,以synchronized(object){}的形式使用,也可以不用synchronized关键字,而是直接采用Lock的方法。乱用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
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)