1.可见性:
volatile关键字主要是用于保证共享变量的可见性。当多个线程同时访问某个共享变量时,如果不加volatile关键字,则可能会出现多个线程同时修改该变量但是其中的某些线程没有看到其他线程对该变量的修改。加上volatile后,该变量的值将被及时更新到主内存中,使得所有线程都能看到最新的值。
synchronized关键字不仅保证了可见性,还保证了原子性和有序性。除了将变量从私有内存同步到主内存外,synchronized还会将线程工作内存中的数据与主内存中的数据进行同步,同时保证了代码块的原子性和有序性。
2.原子性:
volatile关键字仅保证了被修饰变量的读写操作是原子性的。但是,对于复合操作(例如i++),volatile无法保证原子性,因为这是一个复合操作,包括读取、修改、写入三个步骤,并不能保证这三个步骤的连续性。
synchronized关键字可以保证被修饰代码块的原子性,即同一时间只有一个线程能够执行该代码块,其他线程需要等待。
3.适用范围:
volatile关键字适用于只有一个线程写,多个线程读的场景,例如标识位、状态标志等。
synchronized关键字适用于临界区代码,需要保证原子性和有序性的场景,例如对共享资源的读写操作。
4.性能开销:
volatile关键字的性能开销相对较低,因为它仅仅是对变量的可见性进行了保证。
synchronized关键字的性能开销相对较高,因为它需要在进入和退出临界区时获取和释放锁,并且涉及到线程的上下文切换。