首页 > 编程语言 >JUC并发编程学习笔记(二)Lock锁(重点)

JUC并发编程学习笔记(二)Lock锁(重点)

时间:2023-11-02 18:55:07浏览次数:41  
标签:JUC synchronized lock 张票 编程 number 公平 Lock

Lock锁(重点)

传统的synchronized

传统的解决多线程并发导致的一些问题我们会使用synchronized关键字来解决,synchronized的本质就是队列、锁。


Lock的实现类有:可重复锁(最常用)、读锁、写锁

在创建可重复锁时,可传入boolean类型值来决定该锁是公平锁(先来后到)还是非公平锁(可插队)。

三部曲

1、创建一个锁

Lock lock = new ReentrantLock(true);

2、加锁

lock.lock();

3、将业务代码块包裹在try{}cath(){}finally{lock.unlock();}中

try {
            if (number>0){
                System.out.println(Thread.currentThread().getName()+":卖出了第"+ number-- +"张票;"+"剩余"+number+"张票");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

完整给一个业务加锁

class Ticket2{
    private int number = 50;
    Lock lock = new ReentrantLock(true);

    public void sale(){
        lock.lock();
        try {
            if (number>0){
                System.out.println(Thread.currentThread().getName()+":卖出了第"+ number-- +"张票;"+"剩余"+number+"张票");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

公平锁结果

非公平锁结果

从结果上看,非公平锁和synchronized关键字效果一样。

  • 小知识:for循环中的业务逻辑只有一条的时候可以简化大括号,直接将业务逻辑卸载后面通过分号结束。

synchronized和Lock锁的区别

  1. synchronized是关键字,Lock锁是java的一个类
  2. synchronized无法判断锁的状态,Lock锁可以判断是否获取到了锁
  3. synchronized是自动的,执行完之后会自动释放锁;Lock锁必须要手动释放锁!如果不释放锁,会导致死锁
  4. synchronized 线程1(获得锁,阻塞)、线程2(等待,傻等死等);Lock锁在其他线程获得锁阻塞后不一定会一直等待下去。可以通过tryLock来尝试获得锁。
  5. synchronized 可重入锁,不可以中断,非公平锁;Lock 可重入锁,可以判断锁、可以自己设置是否公平
  6. synchronized 适合锁少量的代码同步问题;Lock 适合锁大量的代码同步

标签:JUC,synchronized,lock,张票,编程,number,公平,Lock
From: https://www.cnblogs.com/nhgtx/p/17805951.html

相关文章

  • Java-并发编程-进阶篇
    在上一篇幅中对并发编程进行了简单介绍:并发与并行,进程与线程,以及并发编程的简单代码但是在企业中往往并不能解决实际问题,例如:1.synchronized关键字在企业开发中会大大降低系统的性能2.当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象......
  • JUC并发编程学习笔记(一)认知进程和线程
    进程和线程进程一个程序,如QQ.exe,是程序的集合一个进程往往可以包含多个线程,至少包含一个java默认有两个线程,GC垃圾回收线程和Main线程线程:一个进程中的各个功能java无法真正的开启线程,因为java是运行在虚拟机上的,所以只能通过C++,通过native本地方法调用C++开启线程priva......
  • (四)C#编程基础复习——运算符
    运算符其实就是一个符号,用来告诉编译器执行特定的数学或者逻辑运算。C#中内置了丰富的运算符,大致可以分为以下几类:一、算术运算符算术运算符即完成特定算术运算的符号,例如加、减、乘、除、余等,如下图所示:inta=10;intb=20;Console.WriteLine("a+b={0}",a+b);Console.W......
  • 【转载】CUDA编程学习记录 C++
    参考Yuezero的CUDA编程基础(https://blog.csdn.net/weixin_54338498/article/details/127947551)CUDA编程模型host指代CPU及其内存,包含host程序device指代GPU及其内存,包含device程序经典CUDA程序的执行流程如下:分配host内存,并进行数据初始化;分配device内存,并从host将......
  • (三)C#编程基础复习——数据类型
    C#语言中内置了一些基本的数据类型,数据类型用来指定程序中变量可以存储的数据的类型,C#中的数据类型可以大致分为三类:值类型(Valuetypes);引类型(Referencestypes);指针类型(Pointertypes);一、值类型值类型顾名思义就是有带数值的类型,C#中的值类型有非常多,值类型变量声明后,不......
  • 模拟实现.net中的Task机制:探索异步编程的奥秘
    .net中使用Task可以方便地编写异步程序,为了更好地理解Task及其调度机制,接下来模拟Task的实现,目的是搞清楚:Task是什么Task是如何被调度的基本的Task模拟实现从最基本的Task用法开始Task.Run(Actionaction)这个命令的作用是将action作为一项任务提交给调度器,调度器会安排......
  • 系统编程:控制文件I/O的内核缓冲之sync(),fsync()和fdatasync()
        通过系统编程:从write()和fwrite()谈开来我们知道了系统调用和glibc库函数为了提升性能而设立的缓冲区,那么,什么情况下数据会从上一次缓冲区刷新到下一层存储介质(可能是缓冲区,也可能是永久存储介质)呢?fflush()库函数提供了强制将stdio库函数缓冲区数据刷新到内核缓冲......
  • 实验3 C语言函数应用编程
    任务1源码1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN806voidprint_text(intline,intcol,chartext[]);//函数声明7voidprint_spaces(intn);//函数声明8voidprint_bl......
  • 飞腾派使用内核态编程完成LED20控制操作
    1基础知识在该程序设计过程中我们首先需要学习如何在内核态编程。1.1内核态编程在内核态中编写C语言程序和在用户态中编写C语言程序不同,在用户态中编写C语言程序,我们可以使用libc库,通过系统调用访问内核态的相关操作。基础的内核态程序如下:#include<linux/init.h>#include......
  • shell编程
    H3目标:1.shell是什么2.shell脚本是什么3.理解为什么学习shell脚本4.shell解析器linux系统使用内核操作计算机硬件,通过编写shell命令发送给linux内核去执行,操作计算机硬件,shell是用户操作计算机硬件的桥梁,shell是指令shell是一门设计语言H5shell脚本就是通过shell命......