标签:synchronized int 特性 编译器 线程 保证 排序 三大
synchronized能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。
synchronized (锁对象) {
// 受保护资源
}
一、synchronized保证原子性
案例演示:5个线程各执行1000次 i++;
对number++;增加同步代码块后,保证同一时间只有一个线程操作number++;。就不会出现安全问题。
总结:
synchronized保证原子性的原理,synchronized保证只有一个线程拿到锁,能够进入同步代码块。
二、synchronized保证可见性
案例演示:一个线程根据boolean类型的标记flag, while循环,另一个线程改变这个flag变量的值,另一个线程并不会停止循环。
synchronized保证可见性的原理,执行synchronized时,会对应lock原子操作会刷新工作内存中共享变量的值
三、synchronized保证有序性
3.1 为什么要重排序
为了提高程序的执行效率,编译器和CPU会对程序中代码进行重排序。
3.2 as-if-serial语义
as-if-serial语义的意思是:不管编译器和CPU如何重排序,必须保证在单线程情况下程序的结果是正确的。
以下数据有依赖关系,不能重排序。
写后读:
int a = 1;
int b = a;
写后写:
int a = 1;
int a = 2;
读后写:
int a = 1;
int b = a;
int a = 2;
编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。但是,如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。
int a = 1;
int b = 2;
int c = a + b;
上面3个操作的数据依赖关系如图所示:
如上图所示a和c之间存在数据依赖关系,同时b和c之间也存在数据依赖关系。因此在最终执行的指令序列中,c不能被重排序到a和b的前面。
但a和b之间没有数据依赖关系,编译器和处理器可以重排序a和b之间的执行顺序。
下图是该程序的两种执行顺序。
可以这样:
int a = 1;
int b = 2;
int c = a + b;
也可以重排序这样:
int b = 2;
int a = 1;
int c = a + b;
3.3 使用synchronized保证有序性
总结:
synchronized后,虽然进行了重排序,保证只有一个线程会进入同步代码块,也能保证有序性。
synchronized保证有序性的原理,我们加synchronized后,依然会发生重排序,只不过,我们有同步代码块,可以保证只有一个线程执行同步代码中的代码。保证有序性
标签:synchronized,int,特性,编译器,线程,保证,排序,三大 来源: https://blog.csdn.net/qq_38826019/article/details/119298333
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。