[size=small]我们在处理并发操作的时候经常使用锁机制,大家常用的synchronized和Lock.
1.二者使用方式有所不同:
synchronized可以在方法前或者代码块中,synchronized是java中的内置锁,由jvm控制锁的释放。
Lock使用在代码块中,加锁之后需要显示的释放,一般在finally中释放锁,主要有两种锁ReentrantLock和ReentrantReadWriteLock。
2.二者都是互斥锁,也就是一次只能有一个对象持有该锁。
3.synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其 他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
Lock采用的是乐观锁方式,所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。是非阻塞的。
一般情况下我们使用synchronized就可以满足并发控制,对应高性能的锁机制,我们可以使用ReentrantLock-可重入锁。
java.util.concurrent提供了支持并发数据结构的操作,通过这些我们也可以了解ReentrantLock使用的情形。
ConcurrentHashMap:采用ReentrantLock进行并发控制。
LinkedBlockingDeque:双向阻塞队列,可以作为栈使用,采用ReentrantLock进行并发控制。
LinkedBlockingQueue:阻塞队列,采用ReentrantLock进行并发控制。
如:[/size]
[size=small] 对于阻塞队列,主要是使用take()方法:返回并且移除队列头部元素,当队列中没有可用元素时,处于阻塞等待状态。
源代码如:[/size]
[size=small]可用看到,该方法通过可重入锁ReentrantLock进行并发控制的。其中Condition的
notEmpty.signal()表示唤醒等待中的线程,notEmpty.await()使当前的线程处于等待状态,直到被唤醒或者被中断。[/size]
1.二者使用方式有所不同:
synchronized可以在方法前或者代码块中,synchronized是java中的内置锁,由jvm控制锁的释放。
Lock使用在代码块中,加锁之后需要显示的释放,一般在finally中释放锁,主要有两种锁ReentrantLock和ReentrantReadWriteLock。
2.二者都是互斥锁,也就是一次只能有一个对象持有该锁。
3.synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其 他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
Lock采用的是乐观锁方式,所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。是非阻塞的。
一般情况下我们使用synchronized就可以满足并发控制,对应高性能的锁机制,我们可以使用ReentrantLock-可重入锁。
java.util.concurrent提供了支持并发数据结构的操作,通过这些我们也可以了解ReentrantLock使用的情形。
ConcurrentHashMap:采用ReentrantLock进行并发控制。
LinkedBlockingDeque:双向阻塞队列,可以作为栈使用,采用ReentrantLock进行并发控制。
LinkedBlockingQueue:阻塞队列,采用ReentrantLock进行并发控制。
如:[/size]
/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();
[size=small] 对于阻塞队列,主要是使用take()方法:返回并且移除队列头部元素,当队列中没有可用元素时,处于阻塞等待状态。
源代码如:[/size]
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
[size=small]可用看到,该方法通过可重入锁ReentrantLock进行并发控制的。其中Condition的
notEmpty.signal()表示唤醒等待中的线程,notEmpty.await()使当前的线程处于等待状态,直到被唤醒或者被中断。[/size]