方法 | 作用 |
---|
lock() | 加锁 |
lockInterruptibly() | 可以被打断的锁 |
tryLock(5, TimeUnit.SECOND) | 会等待一段时间。成功返回true,否则返回false |
| |
public class TestLock implement Runnable{
public static ReentrantLock lock = new ReentrantLock();
public static int i = 0;
@override
public void run(){
for(int j = 0;j < 10000;j++){
lock.lock();
try{
i++;
}finally{
lock.unlock();
}
}
}
public static void main(String...args) throws InterruptedException{
TestLock tl = new TestLock();
Thread t1 = new Thread(tl);
Thread t2 = new Thread(t2);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.print(i);
}
}
可重入锁使得一个线程连续多次获得同一把锁,但lock()和unlock()的次数要一样。
与synchronized相比,还多了中断线程的功能。即一个线程在等待锁的时候,可以收到一个通知,去中断线程。可以有效避免死锁
jps -l :看哪个java类正在运行,并记录VMID
jstack -l vmid :看堆栈和锁情况
package atalisas.Crawler;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by 顾文涛 on 2017/8/27.
*/
public class IntLock implements Runnable {
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public IntLock(int lock) {
this.lock = lock;
}
@Override
public void run() {
try{
if (lock == 1){
lock1.lockInterruptibly();
try{
Thread.sleep(500);
}catch (InterruptedException e){}
lock2.lockInterruptibly();
}
else{
lock2.lockInterruptibly();
try{
Thread.sleep(500);
}catch (InterruptedException e){}
lock1.lockInterruptibly();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
if (lock1.isHeldByCurrentThread())
lock1.unlock();
if (lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println(Thread.currentThread().getId()+":Thread Exit");
}
}
public static void main(String...args) throws Exception{
IntLock r1 = new IntLock(1);
IntLock r2 = new IntLock(2);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();t2.start();
Thread.sleep(1000);
t2.interrupt();
}
}
public class TimeLock implements Runnable{
private static ReentrantLock lock = new ReetrantLock();
@override
public void run(){
try{
if(lock.tryLock(5,TimeUnit.SECOND)){
Thread.sleep(60000);
}else{
System.out.print("get lock failed")
}
}catch(InterruptedException e){
}finally{
if(lock.isHeldByCurrentThread())
lock.unlock();
}
}
public static void main(String...args){
TimeLock tl = new TimeLock();
Thread t1 = new Thread(tl);
Thread t2 = new Thread(tl);
t1.start();
t2.start();
}
}
ReentrantLock lock = new ReentrantLock(true);
Condition: 与ReentrantLock合用实现等待/通知模式
方法 | 作用 |
---|
await(), await(time,TimeUnit) | 会使当前线程等待(一段时间)并释放锁,直到被唤醒 |
awaitUninterruptibly() | 不会被中断的线程等待 |
signal(), signalAll() | 唤醒线程 |
public class IntLock implements Runnable {
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
@Override
public void run() {
try{
lock.lock();
condition.await();
System.out.println("Thread is going on!");
}catch (InterruptedException e){}
finally {
lock.unlock();
}
}
public static void main(String...args) throws Exception{
IntLock tl = new IntLock();
Thread t1 = new Thread(tl);
t1.start();
Thread.sleep(2000);
lock.lock();
condition.signalAll();
lock.unlock();
}
}
final void lock() {
acquire(1);
}
=>AbstractQueuedSynchronizer.acquire
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
=>ReentrantLock.FairSync.tryAcquire
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
=>AbstractQueuedSynchronizer.AddWaiter
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
=>AbstractQueuedSynchronizer.enq
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
=>AbstractQueuedSynchronizer.acquireQueued
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}