//【synchronized】(同步互斥):重点理解锁的是哪个对象
//synchronized静态同步方法:锁定的是当前类对象(this)
//synchronized(obj)同步代码块,锁定的是obj对象
锁定对象的所以同步的地方,都会同步互斥
方法互斥的意思就是,第一方法进入了,第二方法就不能进入,它们是互斥的
例如:
线程1 synchronized method 1 (获取this对象锁)
线程2 synchronized method 2
(menthod1和method2是同步互斥的,所以当线程1不管进入方法1还是方法2,他都会获得一把this对象锁,只有它还没有出方法,锁就不会释放,线程2就不能进入这两个
方法中的任意一个方法)
synchronized是通过互斥,达到原子性,可见性,代码顺序性得到满足,sychronized不能保证指令的有序性
【volatile】
1、禁止指令重排序
2、建立了一个内存屏障
只能满足共享变量的可见性和代码顺序性(有序性)
可见性:直接从主内存中操作变量
(volatile对于有序性也就是说,可以禁止指令重排序) (CPU和jvm都有重排序)
(用volatile经常用来保证共享变量的读取操作安全)
它不能保证原子性:
所以对于变量的操作,操作本身如果是原子性的,使用volatile就是线程安全,否则不安全
在每一个线程,自己看自己内部的指令,都是有序,但是其实jvm,cpu是进行了重排序的,这些指令在其他线程看来,都是无序的
(使用sychronized是尽量不用Integer和String,尽量锁定Obj或class)
【wait()、notify()和notifyAll()方法必须要synchronized的同步块里面使用,不在这里面使用就会抛异常】
sychronized(object){ //代表锁定的不是这段代码块,锁定的是这个对象,这个对象所有它可以影响到的同步的地方,全部都会阻塞并等待
//哪个线程掉这段代码,
object.wait() ; // wait()让这把锁进行wait,在wait()所在的代码处停止执行,直到接到通知或被中断为止
}
sleep()只能被interrupt通知
wait()可以被interrupt通知也可以被notify()唤醒
有三个线程ABC
synchronized(object){ //第一行
object.wait(); //第二行
}
线程A进入第一行,BC就在第一行竞争object锁
线程A进入第二行,代表线程阻塞并等待,释放object的锁
线程BC竞争object的锁
wait()搭配notify()可以用在线程间的通信。
notify的含义:唤醒对象的锁,由其它线程竞争这把锁
【notify和notifyAll的区别】:
notify方法只是唤醒了某一个等待线程
notifyAll是一次唤醒所以等待的线程
【等待队列】:
thread.join()
thread.sleep(long)
object.wait()
(以上的阻塞方法,对系统即CPU资源的消耗可以说忽略不计的)
【同步队列】:
synchronized(object)
(所有在同步队列中,由某个对象锁定的过程,在满足一定的条件(指的是获取到锁的线程退出同步区域,或者是调用wait()释放锁),所有满足条件的线程都会出队列来竞争这
把锁)
以后做多线程优化的一种前提条件:
synchronized使用,在某些情况下,比如非常多的线程,执行时间非常短的同步代码,这种时候会不停的让很多线程进出队列,及竞争锁,这种情况对资源消耗是比较大的
synchronized如果锁的是一个类对象,那么这个类当中的所有sychronized静态方法也是同步互斥的。也就是如果两个线程,有一个线程进入了其中一个方法, 另外一个线程就
这所有方法都不能执行。
对于具体某一个对象,这个对象调用同步实例方法,和sychronized(这个对象){},这些代码块内是同步互斥的;//??
所以同一个对象的锁,该对象同步作用代码在某个时间点只能有一个线程执行