您当前的位置: 首页 > 

星夜孤帆

暂无认证

  • 1浏览

    0关注

    626博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Synchronized保证三大特性

星夜孤帆 发布时间:2021-08-01 15:48:59 ,浏览量:1

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后,依然会发生重排序,只不过,我们有同步代码块,可以保证只有一个线程执行同步代码中的代码。保证有序性

视频教程

关注
打赏
1636984416
查看更多评论
立即登录/注册

微信扫码登录

0.0949s