线程同步synchronized和volatile
来源:互联网 发布:大数据时代的重要性 编辑:程序博客网 时间:2024/06/04 23:19
java多线程特性
线程同步具有两个特性:可见性和有序性
java线程间的通信是通过共享变量实现的,假如多个线程共享某个Object对象,该对象被创建在主内存(堆内存)中,每个线程都有自己的工作内存(线程栈). 当线程操作Object对象时,首先从主内存拷贝对象副本到工作内存中,再执行修改变量的代码,最后把工作内存中的Object刷新到主内存中. 假如多个线程都保留Object对象的副本,若某时刻修改Object变量,其他线程也能够看到被修改后的值,此为可见性. 多线程并发执行时,cpu对线程的调度是随机的,最经典的例子是银行汇款问题,我们需要保证取款线程和汇款线程有序的进行,此为有序性.
synchronized
下面用代码说明线程同步的问题
public class TraditionalThreadSynchronized { public static void main(String[] args) { final Outputter output = new Outputter(); new Thread() { public void run() { output.output("zhangsan"); }; }.start(); new Thread() { public void run() { output.output("lisi"); }; }.start(); }}class Outputter { public void output(String name) { // TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符 for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); // Thread.sleep(10); } }}
程序的运行结果为zhlainsigsan
,显然与预期结果不相符,这就是线程同步问题. 我们希望线程执行完output
方法后再切换到其他线程. java使用synchronized
关键字保证某段代码在不同线程间的执行是互斥的.
- 使用
synchronized
将需要互斥的代码块包含起来
{ synchronized (this) { for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); } }}
- 将
synchronized
加在需要互斥的方法上
public synchronized void output(String name) { // TODO 线程输出方法 for(int i = 0; i < name.length(); i++) { System.out.print(name.charAt(i)); }}
这种方式相当于用this锁住整个方法内的代码块,当修饰静态方法时,等价于用xxx.class锁住整个方法内的代码块,用synchronized
修饰的代码块可以看做原子操作.
线程执行互斥方法的过程如下:
1. 获取同步锁
2. 清空工作内存
3. 从主内存拷贝对象副本到工作内存
4. 执行代码
5. 刷新主内存
6. 是放同步锁
由此可见synchronized
既保证共享内存的可见性,又保证程序的有序性.
volatile
volatile是第二种java实现线程同步的机制.
class Test { static volatile int i = 0, j = 0; static void one() { i++; j++; } static void two() { System.out.println("i=" + i + " j=" + j); }}
one方法和two方法还会并发执行,但加上volatile
修饰后,可以将共享变量i和j的改变直接响应到主内存中,但在two方法获取到变量i和获取变量j的值的这段时间内,one方法可能会被执行多次,导致j的值大于i. 所以volatile
仅保证线程间共享内存的可见性,不能保证并发的有序性.
- 线程同步synchronized和volatile
- 线程同步synchronized和volatile
- 线程同步synchronized和volatile
- 线程同步synchronized和volatile
- 线程同步synchronized和volatile
- 线程(二)线程同步synchronized和volatile
- Java线程同步synchronized和volatile
- 【Java多线程】-线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- Java线程(二):线程同步synchronized和volatile
- PLSQL创建表空间,创建用户,添加权限
- 一些内核操作函数
- 数组的equals方法
- 控制程序流程
- 要走出来,接触我的世界
- 线程同步synchronized和volatile
- 【Socket】MFC之编写聊天通信代码
- 电阻噪声的基础知识和一个有趣的小测试
- Andorid studio的目录结构设置
- 简要介绍windows平台下的一些汇编操作
- 文件查找命令 whereis locate find
- shutdown immediate 卡在SMON: disabling tx recovery
- J2SE大完结
- 如何写memset函数