synchronized原理?
synchronized的底层是使用操作系统的mutex lock实现的:当线程释放锁时,JMM会把该线程对应的工作内存中的共享变量刷新到主内存中,当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。synchronized用的锁是存在Java对象头里的。(临界区由monitor的monitorenter和monitorexit实现)
synchronized的作用?
原子性:操作不可中断,多并发情况下同一时间只有一个线程操作锁内容,相当于单线程。
可见性:当线程获得锁的时候会清空工作内存,从主内存更新最新数据,当释放锁的时候会将更新同步到主内存中。有效避免脏读。
有序性:注意,它不能解决重排序问题,那为什么说它是有序的? 因为synchronized锁住后线程相当于单线程,符合as-if-serial原则.不管怎么重排序优化 它都是不影响最后的结果。(synchronized只保证了代码的有序性,但是变量的赋值操作依旧可以被编译器优化,此时会发生指令重排序; 而volatile就是为了防止编译器指令重排序的。)
synchronized详解?
synchronized:同步锁🔒用法:锁的是共享对象。只和对象有关系。
1、修饰类,synchronized(类名.class){} 锁的是这个类的所有对象;
2、修饰代码块,叫同步语句块,锁调用这个代码块的对象。synchronized(object){}
3、修饰方法,叫同步方法,锁调用这个方法的对象。
4、修饰静态方法,作用范围整个静态方法,锁这个类的所有对象。
(注意:有共享数据才会出现线程安全问题,静态方法、静态变量属于类不属于对象,放在方法区,栈是私有的,其他区域都是共享的。局部变量在栈区)
//修饰类
class Person{
private volatile static Person person;
public Person(){
}
public static Person getPerson(){
if(person == null){
synchronized (Person.class){
if(person == null){
person = new Person();
}
}
}
return person;
}
}
//修饰静态方法
class Person1{
private static Person person1;
private Person1(){}
public synchronized static Person getPerson1(){
if(person1==null){
person1= new Person();
}
return person1;
}
}
//修饰代码块
public class SynchronizedDemo {
public void methond() {
// 进入代码块会锁 this 指向对象中的锁;出代码块会释放 this 指向的对象中的锁
synchronized (this) {
}
}
}
//修饰方法
public class SynchronizedDemo {
public synchronized void methond() {
}
}
线程中synchronsize的操作过程?
1、线程状态:启动(NEW)、就绪(RUNNABLE)运行(RUNNING)、阻塞(BLOCKED)、结束(TERMINATED)。(注意线程调度是时间片的抢占方式)
2、线程启动——抢到锁的线程进入运行状态——没抢到锁的线程进入阻塞状态——等到锁释放后,就绪线程开始抢锁———运行完毕后关闭线程
注意事项:
锁内同时只能有一个线程执行,其他线程在阻塞队列或就绪队列中等待释放锁。
锁互斥:thread1争抢到了🔒,正在执行锁里面语句时被调度出去,thread2获得cpu进来发现有🔒就进入阻塞队列里等待thread1释放锁,thread1执行完锁语句后释放锁后,thread才能获得🔒;则thread1和thread2互斥(锁互斥)。
synchronized不能被继承:父类方法有锁,子类继承的方法没锁。synchronized不属于方法的一部分。
定义接口方法时不能使用synchronized;
构造方法不能使用synchronized来修饰,但是可以使用synchronized代码块。
线程抢锁失败就会进入阻塞队列(blocked),等锁释放了再争抢锁。等后台线程执行完了才会结束。
waiting等待集:调用wait()方法线程释放锁进入等待集,一直等待,直到被notify()或notifyAll唤醒。
timed_waiting超时等待:wait()和sleep()等到时间到了继续执行任务。
wait和sleep区别:wait是Object类–sleep是Thread类,wait进入等待集前会释放锁–sleep进入等待集不会释放锁,所有线程都在等他休眠醒来。