可能忽略的Java基础知识-小心使用synchronized和volatile
来源:互联网 发布:python格式化毫秒数 编辑:程序博客网 时间:2024/06/06 09:49
接着 一个三年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
- 可能忽略的Java基础知识-小心使用synchronized和volatile
- java的volatile和synchronized
- 可能忽略的Java基础知识 - 理解内部类和匿名内部类,异常与异常捕获
- PHP一些可能被忽略的基础知识
- java中的volatile和synchronized
- Java中的volatile和synchronized
- Java volatile和synchronized 区别
- java中的volatile和synchronized
- java中的volatile和synchronized
- java 关键字synchronized和volatile
- java中的volatile和synchronized
- java中的volatile和synchronized
- Java多线程volatile和synchronized
- java中的volatile和synchronized
- java中的volatile和synchronized
- java volatile和synchronized区别
- java中的volatile和synchronized
- 使用synchronized和volatile实现Java多线程同步
- HDU 1173(技巧题)
- MFC入门-MCI简单音乐播放器实现
- 玩玩人脸识别
- Netdata Linux下性能实时监测工具
- 条款18:避免使用vector<bool>
- 可能忽略的Java基础知识-小心使用synchronized和volatile
- Win10预览版开始支持Linux命令行
- NYOJ 675 Sinking Ship
- 从原理上搞定编码--Base64编码
- Http请求中Content-Type讲解以及在Spring MVC中的应用
- Spring——jar包详解
- 线性结构总结(2)-线性结构关系与应用
- HDU 1175(搜索DFS)
- C++学习笔记:C++中的new