程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(2)

多线程--线程同步锁Lock锁

发布于2021-03-13 14:06     阅读(494)     评论(0)     点赞(26)     收藏(0)


多线程–线程同步锁–Lock锁-ReentrantLock

之前说了线程同步机制Synchronize锁,其实除此之外还有一种JUC的Lock锁也能实现线程同步。而且Lock实现类ReentrantLock相比Synchronize有更大的灵活性,更加丰富,更是适合大多场景的使用。
先来简单的对比下ReentrantLock和Synchronize吧。

  1. Synchronsize锁是独占锁,加锁和释放锁都是自动的,只要加上关键字synchronize或者代码块就行。使用起来很简单,但是呢灵活性较差。ReentrantLock也是独占锁,但是它需要手动的加锁(lock等)和释放锁(unlock),使用的起来相对复杂了点,但是灵活性好,且ReentrantLock提供了丰富的方法。
  2. Synchronsize和ReentrantLock都是可重入锁(可以多次使用锁:举个例子,方法A使用了锁,其实调用B,但是B也使用了锁,这是调用B的时候不用重新获取锁)。但是都是需要释放锁才能让其它线程拿到锁。
  3. Synchronize一旦拿不到锁,产生了死锁等待状态时,相应不能中断,而ReentrantLock提供了相应中单的锁。
  4. 最主要的就是ReentrantLock还可以实现公平锁机制。什么叫公平锁呢?也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。

与Synchronize不同的是,ReentrantLock提供了多个锁,可以根据不同需求处理线程同步问题。下面我们重点介绍下ReentrantLock锁,Synchronize的介绍请查看之前的博客线程不安全+线程死锁+同步

ReentrantLock是JUC包下的类(java.util.concurrent.locks.ReentrantLock),实现了Lock接口。
在这里插入图片描述
ReentrantLock的释放锁都是一样unlock方法,下面主要看下ReentrantLock不同的锁。
不实现线程同步的时候,不加锁效果:

public class ReenTrantLockThread {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest,"小明").start();
        new Thread(threadTest,"小王").start();
    }
}

class ThreadTest implements Runnable{
    final Lock lock = new ReentrantLock();
    @Override
    public void run() {
        study();
    }

    public void study(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+":我正在学习");
        }
    }
}

结果:
在这里插入图片描述
小明和小王疯由cpu调度学习。加了锁之后,让一个人学习完再下一个线程拿锁学习(注意哦,下一个线程不一定是另一个人哦,由cpu调度)

(1)Lock() 这个锁就是普通也是常用的锁,和Synchronize锁差不多,一旦拿到锁之后必须等待释放锁,才能继续拿锁,否则会出现线程死锁,所以使用结束之后一定要释放锁。
注意:为了防止不释放锁,一般将加锁内容放到try里面,然后在finally里面释放锁,这样保证一定会释放锁。

    public void study(){
        lock.lock();
        try {    /
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+":我正在学习");
            }
        }catch (Exception e){
        }finally {
            lock.unlock()
        }
    }  

结果: 让一个人学习完再下一个线程拿锁学习!!!
在这里插入图片描述

(2) tryLock()锁,我叫它尝试锁,它是用来尝试获取锁,如果能获取到那么可以占有锁使用,如果拿不到我们也可以处理其他事物。它是有返回值的,类型boolean,如果拿到了锁就返回true,拿不到就返回false,所以不管怎么的它都会立马返回一个值。

public void study(){
        boolean flag = lock.tryLock();
        if(flag){
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+":我正在学习");
                }
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }else {
            System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
        }
    }

结果:
在这里插入图片描述
(3)tryLock(long timeout, TimeUnit unit),用法跟tryLock是一样的,不同的是可以指定等待时间,就是锁我拿锁,如果指定时间后还没拿到锁我就返回false,时间没到那我就继续等待锁释放。

public void study() throws InterruptedException {
        boolean flag = lock.tryLock(5000,TimeUnit.MILLISECONDS); // 等待5秒钟拿不到锁就返回false
        if(flag){
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+":我正在学习");
                }
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }else {
            System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
        }
    }

结果:5秒内成功拿到锁。
在这里插入图片描述
我们给线程加上一个sleep,让线程休息总时间超过5秒,
在这里插入图片描述
(4)lockInterruptibly()中断锁,使用这个锁可有主动主断线程使用Thread.interrupt()。前提是这个线程用到锁了,在没有用锁的情况下是用不了的。这个不好演示,用法如下:
在这里插入图片描述
然后说说ReentrantLock特殊的锁机制,公平锁和非公平锁。
就跟字面上意思差不多,
公平锁意思就是哪个线程排队时间长就让谁优点调度。
非公平锁意思就是不管线程啥时候开始排的队,我就让cpu看心情调度。
使用方法非常简单,只需要在初始化锁的时候加上,true(公平)或者false(不公平)参数。默认就是false
公平锁:

final Lock lock = new ReentrantLock(true);
public void study() throws InterruptedException {
        for (int i = 0; i <2 ; i++) {
            try {
                lock.lock(); // 等待5秒钟拿不到锁就返回false
                System.out.println(Thread.currentThread().getName()+":我正在学习");
                //Thread.sleep(2000);
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }
    }

结果:大家不要挤,人人有份。
在这里插入图片描述
非公平锁:

    final Lock lock = new ReentrantLock(false);
    public void study() throws InterruptedException {
        for (int i = 0; i <2 ; i++) {
            try {
                lock.lock(); // 等待5秒钟拿不到锁就返回false
                System.out.println(Thread.currentThread().getName()+":我正在学习");
                //Thread.sleep(2000);
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }
    }

结果:
在这里插入图片描述下片介绍:读写锁。

原文链接:https://blog.csdn.net/qq_31142237/article/details/114648496



所属网站分类: 技术文章 > 博客

作者:zhqu4399

链接:http://www.javaheidong.com/blog/article/114357/4a05db1a350b2e3dc0bd/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

26 0
收藏该文
已收藏

评论内容:(最多支持255个字符)