深入多线程十三:什么是Lock锁,比起synchronized锁有什么区别?(代码示例)

在学习Java的道路上,是否路过多线程时总让你很迷惘;很不巧,我也是,而使我们感到很迷惘主要原因都源于没有对概念的深深的理解和实践。所以我决定漫步Java多线程,同你一起会会多线程。

深入多线程系列

深入多线程一:理解多线程在于深深地理解了多任务、进程、多线程、线程
深入多线程二:手撕多线程,从会三种创建多线程方式开始:除了常见的两种,你是否了解Callable接口方式?
深入多线程三:初遇并发问题:从一个小故事开始,从一行行代码开始
深入多线程四:停止多线程,你不会还以为是用stop和destroy吧?
深入多线程五:多线程为何要使用休眠?
深入多线程六:线程礼让与强制执行
深入多线程七:纯手绘图解多线程状态+代码示例,就问你怕了吗?
深入多线程八:多线程的优先级
深入多线程九:守护线程
深入多线程十:通过案例体会多线程的不安全
深入多线程十一: 超全synchronized的两种用法:同步方法与同步块
深入多线程十二:什么是死锁?
深入多线程十三:什么是Lock锁,比起synchronized锁有什么区别?
深入多线程十四:经典生产者与消费者问题,本质是线程通信问题
深入多线程十五:管程方式解决生产者与消费者问题
深入多线程十六:信号灯方式解决生产者与消费者问题
深入多线程十七:什么是池?线程池方式解决生产者与消费者问题

什么是Lock 锁?

除了synchronized锁,在JDK 1.5,Java提供了更强大的线程同步机制,比起 synchronized 隐式的方式,虽然可以看到它锁的代码片段,但看不到更具体的;不同synchronized锁,Lock锁可以看到它的开始和结束。

(用法也是如此,手动创建Lock锁,需要手动关闭Lock锁)

Lock是显性的方式来实现同步。

手敲代码实现

我们先来看一个会出现问题的多线程

public class ThreadDemo {
    public static void main(String[] args) {
       LockDemo lockdemo = new LockDemo();
       new Thread(lockdemo).start();
       new Thread(lockdemo).start();
    }
}
class  LockDemo  implements Runnable{
    private Integer ticket = 10;
    @Override
    public void run() {
        while (true){
            if(ticket > 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(ticket--);
            }else {
                break;
            }
        }
    }
}

运行结果
在这里插入图片描述

创建Lock锁的格式:

class  LockDemo  implements Runnable {

    private final ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        //加锁
        lock.lock();
        try {
            //线程安全代码块
        } finally {
            //解锁
            lock.unlock();
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
       LockDemo lockdemo = new LockDemo();
       new Thread(lockdemo).start();
       new Thread(lockdemo).start();
       new Thread(lockdemo).start();
    }
}
class  LockDemo  implements Runnable{

    private Integer ticket = 10;

    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true){
            lock.lock();
           try {
                if(ticket > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(ticket--);

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

使用lock锁后的运行结果
在这里插入图片描述

synchronized 与 Lock 的区别

除了上面所说Lock是显式锁synchronized 是隐式锁;synchronized 出了作用域会自动释放,而Lock需要手动开启和关闭。
Lock只有一种代码块锁方式(上面代码示例中的方式),synchronized 有代码块锁和方法锁两种方式(在深入浅出多线程系列十一章节中)
Lock锁在JVM花费调度线程时间比较少,所以性能更好。也有更好扩展性

最后:

最后的最后,为了更好的阅读体验,我把想说的话都放在了下面,嘿嘿。

我是一颗剽悍的种子 把我会的,认真的分享 是我写博客一直不变的信条。
如果你能看到这篇博文,说明咱们还是很有缘的;希望能带给你一些许帮助,创作的不易,
把我文章的知识带走,你的三连留下,点赞,评论,关注,是我最大的动力。

猜你喜欢

转载自blog.csdn.net/A_hxy/article/details/108157071