Synchronized保证三大特性

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

视频教程

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: synchronized关键字可以保证Java中的三大特性,即原子性、可见性和有序性。 原子性synchronized可以将代码块或方法锁定,保证同一时刻只有一个线程可以执行该代码块或方法,从而保证原子性。 可见性:synchronized不仅可以保证原子性,还可以保证线程之间的可见性。当一个线程获取锁时,它会清空工作内存中的数据,从而强制从主内存中读取数据,当释放锁时,它会将修改后的数据刷新到主内存中,从而保证了可见性。 有序性:synchronized可以保证代码块或方法的有序性,即在多线程环境下,代码块或方法的执行顺序是按照程序的顺序执行的,不会出现乱序的情况。 ### 回答2: synchronized是Java中一种重要的同步机制,可以保证代码的安全性和正确性。synchronized保证三大特性,分别是原子性、可见性和有序性。 原子性是指一个操作或一组操作是不可分割的整体,要么全部执行成功,要么全部执行失败,不会产生中间状态。使用synchronized可以保证只有一个线程可以执行synchronized代码块或方法,其他线程需要等待,直到前一个线程执行完毕释放锁。由于只有一个线程执行该代码块,就可以保证该代码块中的操作是原子性的。 可见性是指当一个线程修改一个共享变量的值时,其他线程应该立即知道修改后的值。使用synchronized可以保证共享变量的可见性。当一个线程执行synchronized代码块或方法时,会将修改后的值刷新到内存中,其他线程可以立即读取到修改后的值。 有序性是指程序执行的顺序与代码编写的顺序一致。Java中的指令重排和多线程环境中存在的线程交错执行等问题可能会破坏程序的有序性。使用synchronized可以保证代码执行的有序性。当一个线程先获得锁后执行代码块或方法,在该线程释放锁之前,其他线程无法进入该代码块或方法,因此可以保证代码的有序性。 综上所述,synchronized三大特性保证了代码的安全性和正确性,适用于多线程并发环境中,对于数据的同步操作给予了有效保障。 ### 回答3: synchronized是Java中一个关键字,用于实现线程的同步,它可以保证以下三大特性: 1. 原子性 在多线程环境下,若多个线程同时访问共享数据,那么有可能会产生竞态条件,即其中一个线程修改了数据,而另一个线程却在修改之前对该数据进行了读取,导致数据出现错误的情况。使用synchronized关键字可以解决这个问题,它可以保证一个线程在执行完synchronized代码块之前会锁定该对象,使得其他线程无法修改该对象,从而保证原子性。 2. 可见性 在多线程环境下,若多个线程同时访问共享变量,那么其中一个线程对该变量的修改,不一定会立即被其他线程看到。这是因为不同线程之间的数据是存在缓存中的,当一个线程修改了数据时,如果不通过某种机制同步数据到主内存中,其他线程依旧会从各自的缓存中读取旧数据,从而导致出现数据不一致的情况。通过synchronized关键字可以解决这个问题,它可以将数据同步到主内存中,保证可见性。 3. 有序性 在多线程环境下,若多个线程同时访问共享数据,那么没有任何机制可以保证它们的执行顺序,这就会导致变量的值可能出现意料之外的变化。使用synchronized关键字可以解决这个问题,它可以保证同步代码块的有序性,即在同步代码块内的操作一定会按照代码的书写顺序依次执行。 总之,synchronized关键字在Java中起到了非常重要的作用,它可以保证线程的同步,避免出现竞态条件,并且保证原子性、可见性和有序性,从而使得多线程编程更加安全和稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值