Java多线程复习笔记二-Lock锁机制

77 阅读1分钟

出现背景

java的synchronized的锁太重,又需要保证原子性,所以引入了轻量锁lock锁机制,继承关系如以下图:

image.png

关于Lock锁和synchronized锁的不同之处如以下图所示

简略地说:Lock提供加锁和释放锁的方法,是可控的,而synchronized是不可控的,一旦加锁,只能等待释放 image.png

ReentrantLock

ReentrantLock是主要实现类,ReentrantLock默认为非公平锁(非公平锁可以有效提高吞吐量),关于几种锁的定义,可以查看这篇文章,可保证原子性

image.png Lock继承体系如以下图:

image.png

使用方法如下

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();
    }


    
}

image.png