JAVA锁

1.Lock ()(不死不休)

2.boolean tryLock = lock.tryLock();子线程获取锁(浅尝辄止) 只要别人占用了锁 则就会获取锁失败
new Thread(new Runnable() {
            public void run() {
                //子线程获取锁(浅尝辄止)
                boolean tryLock = lock.tryLock();
                System.out.println("子线程获取锁:"+tryLock);

            }
        }).start();

3.lock.lockInterruptibly();//子线程获取锁(任人摆布) 只要线程被中止获取锁  响应中断

Thread thread = new Thread(new Runnable() {
           public void run() {
               try {
                   lock.lockInterruptibly();
               } catch (InterruptedException e) {
                   e.printStackTrace();
                   System.out.println("this ask me to stop..");
               }
           }
       });
       thread.start();
       Thread.sleep(7000);

       thread.interrupt();

4.lock.unlock();//释放锁

5.Condition condition = new Condition();

object中的wait()  notity,notityAll()只能和synchronized配合使用,可以唤醒一个或者全部(单个等侍集);

Condition需要与Lock配合使用的

a.condition.await();//将子线程挂起
b.condition.signal();//将线程释放

如果signal先于await执行是则会导致死锁现象。

注意点 condition前后都要加lock和unlock否则 报错。

代码如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 〈一句话功能简述〉<br>
 * 〈Condition锁使用〉
 *
 * @author zhaohaiming
 * @create 2019/9/28
 * @since 1.0.0
 */
public class Test_Condition {
    private  static Lock lock = new ReentrantLock();
    private  static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        Thread thread = new Thread(){
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println("here I am ....1");
                    try {
                        condition.await();//将子线程挂起
                        System.out.println("here I am ....2");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }finally {
                    lock.unlock();
                }

            }
        };
        thread.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        lock.lock();
        condition.signal();//将线程释放
        lock.unlock();
    }
}

结论:lock()最常用

2.lockInterruptibly()方法一般更昂贵,有的impl可能没有实现lockInterruputibly(),只有真的需要效应中断时,才使用,使用之前看impl对方法的描述。

二、ReentrantLock锁

lock与unlock一定要匹配使用

实现reentrantLock锁

代码如下:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

/**
 * 〈一句话功能简述〉<br>
 * 〈实现锁〉
 *
 * @author zhaohaiming
 * @create 2019/9/30
 * @since 1.0.0
 */
public class JameLock implements Lock {
    //锁的拥有者
    AtomicReference<Thread> owner = new AtomicReference<Thread>();
    //记录重入次数
    AtomicInteger count = new AtomicInteger(0);
    //等待队列
    private LinkedBlockingQueue<Thread> waiter = new LinkedBlockingQueue<Thread>();
    public boolean tryLock() {
        int ct = count.get();
        //1.判断ct是否为0 如果为ct!=0 则说明锁被占用
        if(ct != 0){
            if(Thread.currentThread() == owner.get()){//如果是当前线程说明重入cout加1
                count.set(ct+1);
                return true;
            }
        }else {
            //2.若ct=0时 说明锁被占 通过cas来抢锁
            if(count.compareAndSet(ct,ct+1)){
                owner.set(Thread.currentThread());
                return  true;
            }
        }
        return false;
    }
    public void lock() {
        //一定要拿到锁
        if(!tryLock()){
            //1.加入等待队列中
            waiter.offer(Thread.currentThread());
            for(;;){//自旋
                //若线程是队列的头部尝试加锁
                Thread head = waiter.peek();
                if(head == Thread.currentThread()){
                    if(!tryLock()){//如果加锁没有成功则将线程挂起
                        //2.将当前线程进行阻塞 挂起
                        LockSupport.park();
                    }else {
                        //获取锁时 则把当前线程退出阻塞队列
                        waiter.poll();
                        return;
                    }
                }else {
                    LockSupport.park();
                }
            }

        }
    }
    public boolean tryUnlock() {
        if(owner.get() != Thread.currentThread()){//如果不是当前线程获取释放锁则抛出异常
            throw new IllegalMonitorStateException();
        }else {
            //unlock 是将count-1
            int ct  = count.get();
            int nextc = ct -1;
            count.set(nextc);
            //如果nextc等于0 则释放锁成功
            if(nextc == 0){
                owner.compareAndSet(Thread.currentThread(),null);
                return  true;
            }else {
                return  false;
            }
        }

    }
    public void unlock() {
        if(tryLock()){
            Thread head = waiter.peek();//获取队列头部线程
            if(head != null){
                LockSupport.unpark(head);
            }

        }

    }
    public void lockInterruptibly() throws InterruptedException {

    }


    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }



    public Condition newCondition() {
        return null;
    }
}

三、ReadWriteLock

1.概念:维护一对关联锁,一个只用于读操作,一个只用于写操作,读锁可以由多个读线程同时 持有,写锁是排他的,同一时间,两把锁不能衩不现线程持有

2.适合场景:适合读取 操作多于写操作的场景,改进互斥锁的性能。如果缓存件

3、锁降级:指的是写锁降级成为读锁,持有写锁的同时,再获取读取读锁,随后取读锁,随后释放写锁的过程

写锁是线程独占,读锁是共享:所以写->读是降级 (读到写  是不能实现的)

实现缓存存取数据

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 〈一句话功能简述〉<br>
 * 〈模拟缓存〉
 *
 * @author zhaohaiming
 * @create 2019/9/30
 * @since 1.0.0
 */
public class CacheData {

    /**
     * 方法功能描述:
      * 实现一个使用Cache数据的方法
     * 如果缓存可用 就
     * 如果缓存不可用,从DB加载数据到缓存 拿到数据之后,需要使用数据 这期间数据 不能发生改变
     * @author zhaohaiming
     * @date   2019/9/30 21:57
     * @return
     *@since: 1.0.0
     */


    public static void main(String[] args) {

    }

}
class TeacherInfoCache{
    static volatile boolean cacheVale;
    static final ReadWriteLock rwl = new ReentrantReadWriteLock();
    static void processCacheData(String dataKey){
        Object data = null;
        rwl.readLock().lock();//先获取读锁
        try {
            if(cacheVale){//如果缓存可用 则从redis里取数据
                data = Redis.data.get(dataKey);

            }else {//从数据库里获取数据
                //先把读锁释放重新获取写锁
                rwl.readLock().unlock();
                //为了避免大量并发访问数据库时 则加上写  只能一个线程访问数据库
                rwl.writeLock().lock();
                try {
                    if (!cacheVale){
                        DataBase.queryUserInfo();
                        Redis.data.put(dataKey,data);
                        cacheVale = true;
                    }else {
                        //锁降级 线程在占有写锁的时候,获取读锁
                        /***
                         * 锁降级 :指的是写锁降级成为读锁,持写写锁的同时,再获取读锁,随后释放写锁的过程。
                         *
                         * 写锁是线程独占共享, 所以写——》读是降级。(读——》写,是不能实现)
                         */
                        rwl.readLock().lock();
                        data = Redis.data.get(dataKey);
                    }
                }finally {
                    rwl.writeLock().unlock();
                }
            }
        }finally {
            rwl.readLock().unlock();//释放锁
        }
    }
}
class DataBase{
    static  String queryUserInfo(){
        System.out.println("查询数据库。。。。");
        return "name :Kody,age:40,gender:ture";
    }
}
class Redis{
    static Map<String,Object> data = new HashMap<String, Object>();
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值