1.ReentrantLock对象
private ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
//代码段
}
finally {
lock.unlock(); // 这步至关重要,千万不能遗漏
}
a.一旦一个线程获得了锁对象,那么其他线程都将阻塞在lock.lock()方法中;
b.锁对象是可重入的(即已经获得锁的线程可以再次获得锁),这时候琐计数+1,当线程调用unlock方法时,琐计数-1,只有当琐计数为0时,才被释放;
c.ReentrantLock类还具有一个带有boolean参数的构造方法,该参数表示是否需要执行公平策略,一个公平锁偏爱等待时间最长的线程(会降低性能),默认是随机选择一个线程获得锁;
2.基于锁的条件变量
a.如何创建一个条件变量?
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
b.如何使用条件变量?
当一个线程获得锁后,发现不具备执行下一步条件时,这时候可以调用condition.await()方法,该方法会导致当前线程释放锁,并且阻塞在当前条件的等待集中;只有当另一个线程调用condition.signalAll()方法或是condition.signal()方法,才能解除阻塞(线程会去重新竞争锁,当再次获得锁后便从await方法返回);
通过条件变量,我们可以简单的实现一个生产者消费者模型(java sdk中代码):
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newC ondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length) // 一定要是while循环
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
c.signal()方法和singalAll()方法的区别:
signalAll方法激活因为该条件而等待的所有线程,而singal只激活其中一个线程;
3.synchronized关键字
a.java中每一个对象都有一个内部锁,如果一个方法用synchronized关键字声明,那么整个方法将被保护起来:
void synchronized method() {
// 代码片段
}
等价于
void method {
this.inner.lock();
try {
// 代码片段
} finally {
this.inner.unlock();
}
}
b.内部对象锁只有一个条件变量,我们可以通过wait方法将线程放入等待集中,也可以通过notif/notifAll方法唤醒等待集中的线程;
c.在静态方法前加synchronized,这时候获得的锁不是对象的内部锁(因为这时候还没对象),获得是当前类字节码锁,所以
public static synchronized void method1 {
}
public static synchronized void method2 {
}
public synchronized void method3 {
}
public synchronized void method4 {
}
method1和method2线程同步,method3和method4线程同步,其余方法之间没有线程同步