显示锁
Lock接口和核心方法
lock() 加锁操作
unlock() 解锁操作
tryLock()
加锁就需要解锁,写代码一定要在finally中记得解锁
public class LockDemo {
private Lock lock = new ReentrantLock();
private int count ;
public void increntCountByLock(){
lock.lock();
try{
count++;
}finally{
lock.unlock();
}
}
可重入锁 ReentrantLock所谓锁的公平和非公平
如果在时间上,先对锁进行获取的请求,一定先被满足,这个锁是公平的,不满足,就是非公平的
非公平锁的效率一般比较高
公平锁和非公平锁效率的比较原理
例如3个线程A,B,C操作一个共享资源,线程 A先获得了共享资源的锁进行操作,此时线程B要对共享资源操作,由于没有获得锁,所以被挂起(挂起和阻塞不是一个概念:挂起是CPU暂时不管,而阻塞是没有满足执行的条件),此时线程C也要来操作共享资源,由于线程B是被挂起的,如果需要将线程B从挂起状态变为运行状态,需要消耗一定的时间,所以先执行活跃的线程C,这样就节约了这个时间,就是非公平锁,如果是公平锁,就会先让B操作,这样效率没有非公平锁效率高了
ReentrantLock构造方法 默认的是公平所,如果需要非公平所
ReentrantLock lock = new ReentrantLock(false)非公平锁
ReadWriteLock接口和读写锁 ReentrantReadWriteLock,什么情况下用读写锁?
ReentrantLock和Synchronized 都是排它锁,一个时刻只允许一个线程操纵
读写锁:同一时刻允许多个读线程同时访问,但是写线程访问的时候,所有的读和写都被阻塞,最适合读多写少的场景
Lock接口和Synchronized的比较
Synchronized 代码简洁,获取锁可以中断,
Lock 获取锁可以被中断,超时获取锁,尝试获取锁,读多写少用读写锁
代码实现 需要操作的共享变量GoodsInfo
public class GoodsInfo {
private final String name;
private double totalMoney;
private int storeNumber;
public GoodsInfo(String name, double totalMoney, int storeNumber) {
this.name = name;
this.totalMoney = totalMoney;
this.storeNumber = storeNumber;
}
public double getTotalMoney(){
return totalMoney;
}
public int getStoreNumber(){
return storeNumber;
}
public void changeNumber(int sellNumber){
this.totalMoney +=sellNumber*25;
this.storeNumber -= sellNumber;
}
}
接口类GoodService
public interface GoodService {
public GoodsInfo getNum();//获得商品信息
public void setNum(int num); //设置商品数量
}
接口实现类UserRWLock 和Synchronized 比较 两个实现类分别实现接口方法
public class UserRWLock implements GoodService{
private GoodsInfo goodsInfo;
private final ReadWriteLock lock = new ReentrantReadWriteLock(false);
private final Lock getLock = lock.readLock();//读锁
private final Lock setLock = lock.writeLock();//写锁
public UserRWLock(GoodsInfo goodsInfo) {
this.goodsInfo = goodsInfo;
}
@Override
public GoodsInfo getNum() {
getLock.lock();
try{
SleepTools.ms(5);
return this.goodsInfo;
}finally {
getLock.unlock();
}
}
@Override
public void setNum(int num) {
setLock.lock();
try{
SleepTools.ms(5);
goodsInfo.changeNumber(num);
}finally{
setLock.unlock();
}
}
}
public class UseSync implements GoodService {
private GoodsInfo goodsInfo;
public UseSync(GoodsInfo goodsInfo){
this.goodsInfo = goodsInfo;
}
@Override
public synchronized GoodsInfo getNum() {
try {
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
return this.goodsInfo;
}
@Override
public synchronized void setNum(int num) {
try {
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
goodsInfo.changeNumber(num);
}
}
工具类
public class SleepTools {
public static void ms(int second){
try {
Thread.sleep(second);
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试类比较两种锁的性能差异 main方法中有注释的是第二种锁的调用,日志信息就打印了,实例代码都在文中有展示,自行运行比较时间可以得出上面比较结论
public class BusiApp {
static final int readWriteRatio = 10; //读写线程的比例
static final int minthreadCount = 3; //最少线程
private static class GetThread implements Runnable{
private GoodService goodService;
public GetThread(GoodService goodService){
this.goodService = goodService;
}
@Override
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
goodService.getNum();
}
System.out.println(Thread.currentThread().getName()
+ "读取商品耗时:"+ (System.currentTimeMillis()-start) + "ms");
}
}
//写操作
private static class SetThread implements Runnable{
private GoodService goodService;
public SetThread(GoodService goodService){
this.goodService = goodService;
}
@Override
public void run() {
long start = System.currentTimeMillis();
Random r = new Random();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
goodService.setNum(r.nextInt(10));
}
System.out.println(Thread.currentThread().getName()
+ "写商品耗时:"+(System.currentTimeMillis()-start) + "ms----");
}
}
public static void main(String[] args) throws InterruptedException {
GoodsInfo goodsInfo = new GoodsInfo("CPU",100000,10000);
//GoodService goodsService = new UseSync(goodsInfo);
GoodService goodsService = new UserRWLock(goodsInfo);
for (int i = 0; i < minthreadCount; i++) {
Thread setT = new Thread(new SetThread(goodsService));
for (int j = 0; j < readWriteRatio ; j++) {
Thread getT = new Thread(new GetThread(goodsService));
getT.start();
}
Thread.sleep(100);
setT.start();
}
}
}