目录
notify()和notifyAll()区别?
-
notify可能会导致死锁,而notifyAll不会
-
任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized 中的代码。使用notifyall,可以唤醒所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。
-
wait() 应配合while循环使用,不应使用if,务必在wait()调用前后都检查条件,如果不满足,必须调用notify()唤醒另外的线程来处理,自己继续wait()直至条件满足再往下执行。
-
notify() 是对notifyAll()的一个优化,但它有很精确的应用场景,并且要求正确使用。不然可能导致死锁。正确的场景应该是 WaitSet中等待的是相同的条件,唤醒任一个都能正确处理接下来的事项,如果唤醒的线程无法正确处理,务必确保继续notify()下一个线程,并且自身需要重新回到WaitSet中
sleep()和wait() 区别?
-
sleep()方法,是属于Thread类中的。而wait()方法,则是属于Object类中的。
-
sleep()方法会使程序暂停指定的时间,让出cpu该其他线程,当指定的时间到了又会自动恢复运行状态。这段过程中,线程不会释放对象锁。
-
当调用wait()方法的时候,线程会释放对象锁,进入该对象的等待池,只有针对此对象调用notify()方法后本线程才进入对象锁池准备,获取对象锁进入运行状态。
volatile关键字
一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后
1)保证了这个变量进行操作时的可见性,即一个线程修改了某个变量的值,新值对其他线程来说是立即可见的,volatile关键字会强制将修改的值立即写入主存。
2)防止了jvm指令重排序。
ps:
-
volatile 不是原子性操作
-
volatile
关键字不能完全保证有序性。虽然它可以保证单个变量的读写操作有序执行,但它不能解决多个变量之间的依赖关系和顺序问题。
Singleton A= new Singleton();
代码分三步执行
为
A
分配内存空间初始化
A
将
A
指向分配的内存地址
synchronized 关键字
主要解决的是多个线程之间访问资源的同步性,可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
如何使用 synchronized?
synchronized
关键字的使用方式:
-
修饰实例方法(锁当前对象实例)
-
给当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁 。
-
-
修饰静态方法(锁当前类)
-
给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。
-
因为静态成员不属于任何一个实例对象,归整个类所有,不依赖于类的特定实例,被类的所有实例共享。
-
-
修饰代码块(锁指定对象/类)
-
对括号里指定的对象/类加锁:
-
synchronized(object)
表示进入同步代码库前要获得 给定对象的锁。 -
synchronized(类.class)
表示进入同步代码前要获得 给定 Class 的锁
-
-
volatile和synchronized?
-
volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
-
volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
-
volatile仅能实现变量的修改可见性,并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性。
-
volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。