出现背景
java的synchronized的锁太重,又需要保证原子性,所以引入了轻量锁lock锁机制,继承关系如以下图:
关于Lock锁和synchronized锁的不同之处如以下图所示
简略地说:Lock提供加锁和释放锁的方法,是可控的,而synchronized是不可控的,一旦加锁,只能等待释放
ReentrantLock
ReentrantLock是主要实现类,ReentrantLock默认为非公平锁(非公平锁可以有效提高吞吐量),关于几种锁的定义,可以查看这篇文章,可保证原子性
Lock继承体系如以下图:
使用方法如下
class NumStore{
private static NumStore numStore;
int num = 10000;
int j=0;
//初始化
private ReentrantLock reentrantLock=new ReentrantLock(true);
public void decr() throws InterruptedException {
/**
* 加锁
* **/
reentrantLock.lock();
if(num>0){
num=num-1;
j=j+1; }
/**
* 释放锁
* **/
reentrantLock.unlock(); }
public int getNum(){
return num; }
}
实现读写锁
读写锁与传统意义上的S锁和X锁是一致的,写锁是独占,读锁是可以多线程共享的,结果也如运行结果所示,实现Lock的ReadLock和WriteLock是静态类,使用ReentrantLock调用类方法
public class Demo1 {
public static void main(String[] args) {
A lock=new A();
for(int i=0;i<=100;i++){
new Thread(()->{
for(int j=0;j<=100;j++){
try {
lock.addNum();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.getNum();
}
},"线程是 "+String.valueOf(i)).start();
}
lock.getNum();
}
}
class A{
int num=1000;
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
void addNum() throws InterruptedException {
reentrantReadWriteLock.writeLock().lock();
this.num=this.num+1;
System.out.println("写的"+Thread.currentThread().getName()+","+num);
reentrantReadWriteLock.writeLock().unlock();
Thread.sleep(3);
}
void getNum(){
reentrantReadWriteLock.readLock().lock();
System.out.println("读的"+Thread.currentThread().getName()+","+num);
reentrantReadWriteLock.readLock().unlock();
}
}