diff --git "a/\345\255\246\344\271\240\347\233\270\345\205\263/\345\260\261\344\270\232/\350\256\241\347\256\227\346\234\272\345\270\270\350\200\203\345\205\253\350\202\241\346\226\207\346\200\273\347\273\223/Java\345\237\272\347\241\200/\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201/index.md" "b/\345\255\246\344\271\240\347\233\270\345\205\263/\345\260\261\344\270\232/\350\256\241\347\256\227\346\234\272\345\270\270\350\200\203\345\205\253\350\202\241\346\226\207\346\200\273\347\273\223/Java\345\237\272\347\241\200/\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201/index.md" index 2cb083f..6f74ab0 100644 --- "a/\345\255\246\344\271\240\347\233\270\345\205\263/\345\260\261\344\270\232/\350\256\241\347\256\227\346\234\272\345\270\270\350\200\203\345\205\253\350\202\241\346\226\207\346\200\273\347\273\223/Java\345\237\272\347\241\200/\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201/index.md" +++ "b/\345\255\246\344\271\240\347\233\270\345\205\263/\345\260\261\344\270\232/\350\256\241\347\256\227\346\234\272\345\270\270\350\200\203\345\205\253\350\202\241\346\226\207\346\200\273\347\273\223/Java\345\237\272\347\241\200/\345\244\232\347\272\277\347\250\213\345\222\214\351\224\201/index.md" @@ -219,7 +219,6 @@ public class MyObject { } ``` - 实际上,Lock 的实现基本都是通过聚合了一个同步器 AQS(AbstractQueuedSynchronizer)来实现的,AQS 是一种基于 CLH 队列的锁实现,是一种非常高效的锁实现。其目的是为了保证锁的可重入性和线程安全性,底层算法必然是 FIFO 队列。 AQS 的主要使用方式是继承,通过继承 AQS,实现自己的同步器,然后通过`Lock`接口的实现类来使用。在使用过程中,对同步状态进行更改主要有如下几个方法: @@ -250,12 +249,12 @@ AQS 的主要使用方式是继承,通过继承 AQS,实现自己的同步器 显式锁和隐式锁是 Java 中的两种锁实现,各有优缺点。 1. 显式锁(`Lock`接口): - - 优点:显式锁是一种更加灵活的锁,可以实现更多的功能,如可重入锁、读锁、写锁、公平锁、自旋锁、分段锁等。 - - 缺点:显式锁需要手动加锁和解锁,容易出现死锁、忘记解锁等问题,使用复杂,代码量较多。 + - 优点:显式锁是一种更加灵活的锁,可以实现更多的功能,如可重入锁、读锁、写锁、公平锁、自旋锁、分段锁等。 + - 缺点:显式锁需要手动加锁和解锁,容易出现死锁、忘记解锁等问题,使用复杂,代码量较多。 2. 隐式锁(`synchronized`关键字): - - 优点:隐式锁是一种简单易用的锁,不需要手动加锁和解锁,JVM 会自动帮助加锁和解锁,使用方便,没有内存泄漏的风险。 - - 缺点:隐式锁功能较为简单,只能实现基本的加锁和解锁,不支持可重入锁、读锁、写锁、公平锁等功能,不可以跨方法调用,不可以设置等待时间不能监控锁状态。 + - 优点:隐式锁是一种简单易用的锁,不需要手动加锁和解锁,JVM 会自动帮助加锁和解锁,使用方便,没有内存泄漏的风险。 + - 缺点:隐式锁功能较为简单,只能实现基本的加锁和解锁,不支持可重入锁、读锁、写锁、公平锁等功能,不可以跨方法调用,不可以设置等待时间不能监控锁状态。 总的来说,显式锁更加灵活,功能更加丰寶,但使用复杂,代码量较多;隐式锁简单易用,但功能较为简单,只能实现基本的加锁和解锁。 @@ -282,19 +281,15 @@ AQS 的主要使用方式是继承,通过继承 AQS,实现自己的同步器 ## 讲讲`volatile`关键字的作用 -很多人说`volatile`关键字是 Java 中的轻量级锁,这个说法是不准确的。`volatile`关键字是一种内存屏障,用来保证变量的可见性和有序性,不是一种锁。 - -`volatile`关键字是 Java 中的修饰符,用来修饰变量,保证变量的可见性和有序性。 +`volatile`关键字是 Java 中的修饰符,用来修饰变量,作用是为了解决多线程并发访问共享变量的问题,保证变量的可见性和有序性。 -`volatile`关键字的作用是为了解决多线程并发访问共享变量的问题,保证变量的可见性和有序性。 +很多人说`volatile`关键字是 Java 中的轻量级锁,这个说法是不准确的。`volatile`关键字是一种内存屏障,不是一种锁。 `volatile`关键字的特点如下: 1. 可见性:`volatile`关键字保证变量的修改对其他线程是可见的,一个线程修改了`volatile`变量的值,其他线程可以立即看到修改后的值。 2. 有序性:`volatile`关键字保证变量的读写操作是有序的,一个线程写入了`volatile`变量的值,其他线程可以立即看到写入的值。 -`volatile`关键字的使用场景是在多线程并发访问共享变量的情况下,保证变量的可见性和有序性。 - 其具体实现涉及到了 Java 内存模型(JMM)的相关知识。JMM 中规定,所有共享变量都存储在主内存中,每个线程都有自己的工作内存,线程对共享变量的操作都是在工作内存中进行的,线程之间的共享变量不可见。 为了保障可见性,除了使用`synchronized`关键字外,还可以使用`volatile`关键字。`volatile`关键字修饰的变量在被进行读写操作时,会直接越过工作内存,在主内存中进行操作,从而保证了变量的可见性。