Java多线程:Lock锁(未完待续)

这篇具有很好参考价值的文章主要介绍了Java多线程:Lock锁(未完待续)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Lock锁的基本使用

在Java中,Lock是一个接口,它提供了比synchronized关键字更高级的线程同步机制。使用Lock接口可以创建更复杂和灵活的同步结构。

Lock接口的常用实现类有ReentrantLock和ReentrantReadWriteLock,它们提供了可重入的互斥锁和读写锁。

相比synchronized来实现同步,使用Lock实现同步主要有以下差异性:

  1.  使用synchronized关键字时,锁的控制和释放是在synchronized同步代码块的开始和结束位置。而在使用Lock实现同步时,锁的获取和释放可以在不同的代码块、不同的方法中。这一点是基于使用者手动获取和释放锁的特性。
  2.  Lock接口提供了试图获取锁的tryLock()方法,在调用tryLock()获取锁失败时返回false,这样线程可以执行其它的操作 而不至于使线程进入休眠。tryLock()方法可传入一个long型的时间参数,允许在一定的时间内来获取锁。
  3.  Lock接口的实现类ReentrantReadWriteLock提供了读锁和写锁,允许多个线程获得读锁、而只能有一个线程获得写锁。读锁和写锁不能同时获得。实现了读和写的分离,这一点在需要并发读的应用中非常重要,如lucene允许多个线程读取索引数据进行查询但只能有一个线程负责索引数据的构建。
  4.  基于以上3点,lock来实现同步具备更好的性能。

使用Lock:

创建Lock对象。

// 创建Lock对象
Lock lock = new ReentrantLock();
```

在需要进行同步的代码块中,通过调用`lock()`方法来获取锁。

lock.lock();
try {
    // 同步的代码
} finally {
    // 在finally块中释放锁,以确保锁的释放
    lock.unlock();
}
```

示例代码如下,多种方式进行代码块同步:

package ch12;


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


/**
 * @copyright 2003-2024
 * @author    qiao wei
 * @date      2024-01-10
 * @version   1.0
 * @brief     
 * @history   
 */
public class SellTicketThread extends Thread {
    
    public SellTicketThread() {
        ticket = 0;
        lock = new ReentrantLock();
    }

    @Override
    public void run() {
        super.run();
        
//        run01();
        runUseLock04();
    }
    
    private void runUseSynchronized() {
        while (true) {
            synchronized (SellTicketThread.class) {
                if (100 >= ticket) {
                    ++ticket;
//                    sleep(100);
                    System.out.println(getName() + "正在卖第" + ticket + "门票");
                } else {
                    break;
                }
            }
        }
    }
    
    /**
     * @author  qiao wei
     * @brief   先处理,后break流程。多处使用类Lock的unlock方法。
     * @param   
     * @return  
     * @throws  
     * @history 
     */
    private void runUseLock01() {
        while (true) {
            if (100 >= ticket) {
                lock.lock();
                if (100 >= ticket) {
                    ++ticket;
                    System.out.println(getName() + "正在卖第" + ticket + "门票");
                } else {
                    lock.unlock();
                    break;
                }

                lock.unlock();
            } else {
                // 退出while循环语句。
                break;
            }
        }
    }
    
    /**
     * @author  qiao wei
     * @brief   先处理,后break流程。使用try/finally流程处理类Lock的unlock方法。
     * @param   
     * @return  
     * @throws  
     * @history 
     */
    private void runUseLock02() {
        while (true) {
            if (100 >= ticket) {
                try {
                    lock.lock();
                    if (100 >= ticket) {
                        ++ticket;
                        System.out.println(getName() + "正在卖第" + ticket + "门票");
                    } else {
                        break;
                    }
                } finally {
                    // 唯一解锁处。
                    lock.unlock();
                }
            } else {
                // 退出while循环语句。
                break;
            }
        }
    }
    
    /**
     * @author  qiao wei
     * @brief   先break,后处理流程。多处使用类Lock的unlock方法。
     * @param   
     * @return  
     * @throws  
     * @history 
     */
    private void runUseLock03() {
        while (true) {
            if (100 == ticket) {
                break;
            } else {
                lock.lock();

                if (100 == ticket) {
                    lock.unlock();

                    // 退出while循环语句。
                    break;
                } else {
                    ++ticket;
                    System.out.println(getName() + "正在卖第" + ticket + "门票");
                }

                lock.unlock();
            }
        }
    }
    
    /**
     * @author  qiao wei
     * @brief   先break,后处理流程。使用try/finally流程处理类Lock的unlock方法。
     * @param   
     * @return  
     * @throws  
     * @history 
     */
    private void runUseLock04() {
        while (true) {
            if (100 == ticket) {
                break;
            } else {
                lock.lock();

                try {
                    if (100 == ticket) {
                        break;
                    } else {
                        ++ticket;
                        System.out.println(getName() + "正在卖第" + ticket + "门票");
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    }
    
    /**
     * @author qiao wei
     * @brief  要出售的总票数。
     */
    private static int ticket;
    
    /**
     * @author qiao wei
     * @brief  同步锁。
     */
    private static Lock lock;
}

测试验证:

package ch12;


/**
 * @copyright 2003-2024
 * @author    qiao wei
 * @date      2024-01-10
 * @version   1.0
 * @brief     
 * @history   
 */
public class TestSynchronized {
    
    public TestSynchronized() {}

    public static void main(String[] args) {
        SellTicketThread thread01 = new SellTicketThread();
        SellTicketThread thread02 = new SellTicketThread();
        SellTicketThread thread03 = new SellTicketThread();
        
        thread01.start();
        thread02.start();
        thread03.start();
    }
}

注意事项:

加锁(lock或synchronized)必须在循环(while)里面,不软会导致一个线程占用所有资源,而不是多线程切换。文章来源地址https://www.toymoban.com/news/detail-781568.html

到了这里,关于Java多线程:Lock锁(未完待续)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vivado使用记录(未完待续)

    字体大小修改:Setting、Font Quick Start 组包含有 Create Project(创建工程)、 Open Project(打开工程)、 Open Example Project(打开实例工程)。 Tasks 组包含有 Manage IP(管理 IP)、 Open Hardware Manager(打开硬件管理器)、 Xilinx Tcl Store( Tcl 脚本存储库)。 Learning Center 组包含有 Documen

    2024年03月09日
    浏览(46)
  • 机器学习基础(粗学)【未完待续】

    卷积:用卷积求系统的存量 卷积,就是把输出函数反转一下。。。。(离谱) 实际不是从物理意义上理解的函数翻转,而是应该从数学意义上,去理解卷积的意义。 在定义卷积时为什么要对其中一个函数进行翻转? - 中微子的回答 - 知乎 图像的卷积操作:图像元素与

    2024年02月04日
    浏览(51)
  • 卫星下行链路预算模型(未完待续)

    1. 接收端天线模型 简单一些,考虑地球同步卫星多波束通信系统,波束指向固定。波束数量为 N b N_b N b ​ . 波束中心在地面的位置可以用经度向量和纬度向量表示: P ⃗ l g = [ l 1 , l 2 , . . . , l N b ] P ⃗ l a = [ a 1 , a 2 , . . . , a N b ] vec{P}_{lg} = [l_1, l_2,...,l_{N_b}] \\\\ vec{P}_{la} = [a_

    2024年02月03日
    浏览(39)
  • PHP复习资料(未完待续)

    特别鸣谢:@NLER提供雨课堂数据 (未完待续,请持续关注此板块) 【计科三四】雪课堂PHP期末模拟题:https://ks.wjx.top/vm/tUAmjxq.aspx# 【计科一二】PHP第一章练习题 https://ks.wjx.top/vm/QnjHad4.aspx# 【计科一二】PHP第二章练习题 https://ks.wjx.top/vm/h2FvEVI.aspx# 【计科一二】PHP第三章练习题

    2024年02月07日
    浏览(41)
  • [DASCTF7月赛](未完待续~)

    misc Coffee desu! hint1: Strange Protocol 经过搜索,发现这个是一种恶搞协议: 自定义了一些请求方式 结合首页英文: 我们需要使用 BREW 向服务器添加 milktea 返回: 这个协议定义了: Accept-Additions 头,于是我们添加上: milktea [外链图片转存失败,源站可能有防盗链机制,建议将图片保

    2024年02月16日
    浏览(41)
  • Provide/Inject 依赖注入(未完待续)

    父组件传递给子组件数据,通过props,但是需要逐层传递 provide/Inject 的推出就是为了解决这个问题,它提供了一种组件之间共享此类值的方式,不必通过组件树每层级显示地传递props 目的是为了共享那些被 认为对于一个组件树而言是全局的数据 provide 接受两个参数:第一个参

    2024年01月20日
    浏览(41)
  • 新电脑Mac安装前端环境,未完待续~

    电脑:MacBook Pro (15-inch, 2017) 版本接近可以用迁移助理 太久远就只能新电脑环境重装了, 微信小程序,支付宝小程序,安卓,IOS 无非这几种 以下就是一名前端小程序开发人员环境配置步骤 仅供参考 纯新电脑安装 ——————————————前端常用的工具安装————

    2024年02月09日
    浏览(54)
  • 源码学习:web server althttpd (未完待续)

    https://sqlite.org/althttpd/dir?ci=tip (推荐) https://github.com/jesrui/althttpd/tree/master (旧版本) https://sqlite.org/althttpd/file?name=althttpd.mdci=tip 轻量级 web 服务器,设计宗旨是追求简洁、安全和低资源占用。 设计理念 Althttpd通常是通过xinetd、systemd或类似的工具启动的。针对每个传入的连接

    2024年01月21日
    浏览(39)
  • kafka大数据采集技术实验(未完待续)

    下载地址:https://link.zhihu.com/?target=https%3A//kafka.apache.org/downloads 解压 启动zookeeper 需要注意的是 : \\\" c o n f i g / z o o k e e p e r . p r o p e r t i e s \\\" 目录和 \\\" / c o n f i g / z o o k e e p e r . p r o p e r t i e s \\\" 目录是不同的 . 前者指当前目录中 c o n f i g 目录下的 z o o k e e p e r . p r o p e r t

    2024年04月29日
    浏览(82)
  • QT实战之翻金币游戏【未完待续】

    目录 前言 一、游戏整体分析 二、创建项目 三、添加资源 四、主界面实现 1、设置游戏主场景基本配置 2、设置背景图片 3、创建开始按钮并设置动画 4、创建关卡选择界面并实现主界面与其的切换 五、关卡选择界面实现 1、设置关卡选择场景基本配置 2、设置关卡选择场景的

    2024年02月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包