volatile,Lock、ReentrantLock、Theadlocal与synchronized的区别

volatile与synchronized

1)volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
2)volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
3)volatile仅能实现变量的修改可见性,而synchronized则可以保证变量的修改可见性和原子性.

  《Java编程思想》上说,定义long或double变量时,如果使用volatile关键字,就会获得(简单的赋值与返回操作)原子性
4)volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.

5、当一个域的值依赖于它之前的值时,volatile就无法工作了,如n=n+1,n++等。如果某个域的值受到其他域的值的限制,那么volatile也无法工作,如Range类的lower和upper边界,必须遵循lower<=upper的限制。

6、使用volatile而不是synchronized的唯一安全的情况是类中只有一个可变的域。

只有在某些场合才能够使用volatile。使用它必须满足如下两个条件:

  1. 对变量的写操作不依赖当前值;
  2. 该变量没有包含在具有其他变量的不变式中。

volatile可以保证可见性,依据happened-before原则可以保证顺序性。

synchronized锁的机制可以保证原子性,可见性,顺序性。同一时间只有一个线程是保证的基础

Lock与synchronized 区别:

1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;

2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;

3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;

4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;

5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)

6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

ReentrantLock与synchronized的区别

  1. 与synchronized相比,ReentrantLock提供了更多,更加全面的功能,具备更强的扩展性。例如:时间锁等候,可中断锁等候,锁投票。
  2. ReentrantLock还提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活,所以在多个条件变量和高度竞争锁的地方,ReentrantLock更加适合(以后会阐述Condition)。
  3. ReentrantLock提供了可轮询的锁请求。它会尝试着去获取锁,如果成功则继续,否则可以等到下次运行时处理,而synchronized则一旦进入锁请求要么成功要么阻塞,所以相比synchronized而言,ReentrantLock会不容易产生死锁些。
  4. ReentrantLock支持更加灵活的同步代码块,但是使用synchronized时,只能在同一个synchronized块结构中获取和释放。注:ReentrantLock的锁释放一定要在finally中处理,否则可能会产生严重的后果。
  5. ReentrantLock支持中断处理,且性能较synchronized会好些。

Theadlocal与synchronized的区别

ThreadLocal不能使用原子类型(如java.util.concurrent.atomic),只能使用Object类型。ThreadLocal的使用比synchronized要简单得多。

ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。

当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。

猜你喜欢

转载自blog.csdn.net/qq_35240226/article/details/82918751