synchronized关键字:表示“同步”的。它可以对“多行代码”进行“同步”——将多行代码当成是一个完整的整体,一个线程如果进入到这个代码块中,会全部执行完毕,执行结束后,其它线程才会执行。这样可以保证这多行的代码作为完整的整体,被一个线程完整的执行完毕。
synchronized被称为“重量级的锁”方式,也是“悲观锁”——效率比较低。
格式:
synchronized(锁对象){}
锁对象:
1.语法上,可以是任意类的对象
2.如果多条线程想要实现同步,那么这多条线程的锁对象必须一致
b.同步方法:
格式:
修饰符 synchronized 返回值类型 方法名(形参列表){ }
锁对象:
非静态同步方法: 锁对象this
静态同步方法:该方法所在类的字节码对象(类名.class)
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock():加同步锁。
public void unlock():释放同步锁。
synchronized 是JVM层面的锁,是Java关键字,通过monitor对象来完成(monitorenter与monitorexit),对象只有在同步块或同步方法中才能调用wait/notify方法,ReentrantLock 是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁。
synchronized 的实现涉及到锁的升级,具体为无锁、偏向锁、自旋锁、向OS申请重量级锁,
ReentrantLock 实现则是通过利用CAS(CompareAndSwap)自旋机制保证线程操作的原子性和volatile保证数据可见性以实现锁的功能。
synchronized 不需要用户去手动释放锁,synchronized 代码执行完后系统会自动让线程释放对锁的占用; ReentrantLock则需要用户去手动释放锁,如果没有手动释放锁,就可能导致死锁现象。一般通过lock()和unlock()方法配合try/finally语句块来完成,使用释放更加灵活。
synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成; ReentrantLock则可以中断,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中,调用interrupt方法进行中断。
synchronized为非公平锁 ReentrantLock则即可以选公平锁也可以选非公平锁,通过构造方法new ReentrantLock时传入boolean值进行选择,为空默认false非公平锁,true为公平锁。
volatile是一个"变量修饰符",它只能修饰"成员变量",它能强制线程每次从主内存获取值,并能保证此变量不会被编译器优化。
volatile能解决变量的可见性、有序性;
volatile不能解决变量的原子性
死锁:多个线程同时被阻塞,它们中的个或者全部都在等待某个资源被释放。由于线程被限期地阻塞,因此程序不可能正常终。
产死锁的四个必要条件,为了避免死锁,我们只要破坏产死锁的四个条件中的其中个就可以了。
避免死锁最简单的方法就是 阻止循环等待条件 ,将系统中所有的资源设置标志位、排序,
规定所有的进程申请资源必须以一定的顺序(升序或降序) 做操作来避免死锁。