多线程--Lock锁

简介: 多线程--Lock锁

@[toc]

Lock锁

在 jdk1.5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,Lock 接口提供了与 synchronized 关键字类似的同步功能,但需要在使用时手动获取锁和释放锁,且在使用上比synchronized更加灵活。

1、使用ReentrantLock实现同步

在这里插入图片描述

案例:

package com.yxl.demo.ThreadTest;

public class test5 {

    public static void main(String[] args) {

        TestDemo thread = new TestDemo();
        Thread t1 = new Thread(thread,"窗口一");
        Thread t2 = new Thread(thread,"窗口二");
        t1.start();
        t2.start();
    }
}

class TestDemo implements Runnable{
    //共享的火车票变量
    private  int count = 100;

    //重寫run方法
    @Override
    public void run() {
        while (count > 0){
            try {
                //休眠一下 方便出现并发问题
                Thread.sleep(50);
            }catch (Exception e){
                e.getMessage();
            }
            sale();
        }
    }
    //卖票
    public void sale(){
        if(count > 0){
            System.out.println(Thread.currentThread().getName() +"出售 :" +(100 -  count + 1));
            count--;
        }
    }
}

运行结果如下:会发现出现卖重复票的问题

除了 内置锁(Synchronized)解决方案,我们可以使用 Lock锁解决

synchronized的缺陷
synchronized是Java中的一个关键字。

我们知道如果一段代码被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块的时候,其他的线程便只能一直等待,等待获取锁的线程释放锁,而这里获锁的线程释放锁有两种情况:

  1. 获取锁的线程执行完了该代码块,然后线程释放对锁的占有;
  2. 线程执行发生异常,此时JVM会让线程自动释放锁。

如果这个获取锁的线程由于I/O或者其他原因(如调用sleep方法)被阻塞了,但是有没有释放锁,其他线程便只能干巴巴地等待,这会很影响执行效率。

因此就需要一种机制可以不让等待的线程一直无限期地等待下去(如只等待一定的时间或者能够响应中断),通过Lock就可以办到。

再如:当有多个线程读取文件时,读操作和写操作会发生冲突,写操作和写操作会发生冲突,但是读操作和读操作不会发生冲突。

如果此时采用synchronized关键字就会出现一个问题:如果多个线程只是进行读操作,所以当一个线程进行读操作时,其他的线程只能等待无法进行读操作。

因此就需要 一种机制使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。

另外,通过Lock可以知道线程有没有成功获取锁,这是synchronized无法办到的。

注意:

  1. Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性,Lock是一个类(接口),通过这个类可以实现同步访问;
  2. 使用synchronized不需要用户手动去释放锁,当synchronized方法或代码块执行完后,系统会自动让线程释放对锁的占用;而Lock则必须要用户手动释放锁,如果没有主动释放,就有可能导致出现死锁。

使用Lock锁案例

package com.yxl.demo.ThreadTest;

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

public class test5 {

    public static void main(String[] args) throws InterruptedException {

        TestDemo thread = new TestDemo();
        Thread t1 = new Thread(thread,"窗口一");
        Thread t2 = new Thread(thread,"窗口二");
        t1.start();
        t2.start();
    }
}

class TestDemo implements Runnable{
    //共享的火车票变量
    private  int count = 100;
    //重寫run方法
    @Override
    public void run() {
               while (count > 0) {
                       sale();
           }
        }
    public  void sale() {
        Lock lock  = new ReentrantLock();
        lock.lock();
        try {
            if (count > 0) {
                System.out.println(Thread.currentThread().getName() + "出售 :" + (100 - count + 1));
                count--;
            }
        }catch (Exception e){
        }finally {
            //一定在finally中释放锁
            lock.unlock();
        }
    }
}

lock.lock() 获取锁
lock.unlock() 释放锁,但要在 finally中使用

lock.trylock() 获取锁 ,也要结合 try catch 一起使用

相关文章
|
2月前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
43 2
|
6天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
32 4
|
30天前
|
Java 开发者
在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选
【10月更文挑战第6天】在 Java 多线程编程中,Lock 接口正逐渐取代传统的 `synchronized` 关键字,成为高手们的首选。相比 `synchronized`,Lock 提供了更灵活强大的线程同步机制,包括可中断等待、超时等待、重入锁及读写锁等高级特性,极大提升了多线程应用的性能和可靠性。通过示例对比,可以看出 Lock 接口通过 `lock()` 和 `unlock()` 明确管理锁的获取和释放,避免死锁风险,并支持公平锁选择和条件变量,使其在高并发场景下更具优势。掌握 Lock 接口将助力开发者构建更高效、可靠的多线程应用。
23 2
|
2月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
1月前
|
运维 API 计算机视觉
深度解密协程锁、信号量以及线程锁的实现原理
深度解密协程锁、信号量以及线程锁的实现原理
31 1
|
27天前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
31 0
|
2月前
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
34 7
|
1月前
|
安全 调度 数据安全/隐私保护
iOS线程锁
iOS线程锁
25 0
|
1月前
|
Java API
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
28 0
|
1月前
|
安全 Java 程序员
【多线程-从零开始-肆】线程安全、加锁和死锁
【多线程-从零开始-肆】线程安全、加锁和死锁
41 0