Lock接口方法 | 功能 |
---|---|
lock.lock | 获取锁 阻塞 |
lock.tryLock | 获取锁 成功返回true 失败false |
lock.tryLock(1, TimeUnit.SECONDS) | 等待制定时间 获取锁 成功返回true 失败false |
lock.lockInterruptibly | 注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出 调用Thread.interrupt方法打断 |
lock.unlock | 释放锁 |
设置公平锁 | Lock lock = new ReentrantLock(true);//true为公平锁 |
synchronized 与 Lock接口功能区别
类别 | synchronized | Lock |
---|---|---|
存在层次 | Java的关键字,在jvm层面上 | 是一个类 |
锁的释放 | 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁 | 在finally中必须释放锁,不然容易造成线程死锁 |
锁的获取 | 假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待 | 分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待 |
锁状态 | 无法判断 | 可以判断 |
锁类型 | 可重入 不可中断 非公平 | 可重入 可判断 可公平(两者皆可) |
性能 | 用CAS来实现 | 用CAS来实现 |
功能 | synchronized的使用简单点 | Lock提供的功能丰富点 |
Demo简单示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*
* @author gyn 实现一个线程安全的计数器
*/
public class Test100 implements Runnable {
public final static ExecutorService EXECUTOR = Executors.newFixedThreadPool(100);
public static volatile int li = 0;
public static volatile int si = 0;
public final static Lock lock = new ReentrantLock(true);//公平锁
/**
* Lock实现
*/
public static void getLockInt() {
lock.lock();// 获取锁
try {
li++;
} catch (Exception e) {
// TODO: handle exception
} finally {
lock.unlock();// 释放锁
}
}
/**
* synchronized关键字实现
*/
public static synchronized void getSynInt() {
si++;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
getSynInt();
}
for (int i = 0; i < 100; i++) {
getLockInt();
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
EXECUTOR.execute(new Test100());
}
EXECUTOR.shutdown();
for (;;) {
// 判断线程池任务是否执行完毕
if (EXECUTOR.isTerminated()) {
System.out.println("Lock实现 li=" + Test100.li);
System.out.println("synchronized关键字实现 si=" + Test100.si);
break;
} else {
System.out.println("线程未结束");
Thread.sleep(200);
}
}
}
}
控制台输出-----------------都是线程安全的
线程未结束
Lock实现 li=10000
synchronized关键字实现 si=10000