Java中Lock锁详解

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

 

目录

 一、Lock锁的基本使用

 二、Condition类详解 

 三、进程的优先级

四、wait/join与sleep的区别:


 一、Lock锁的基本使用

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

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

使用Lock锁的一般步骤如下:

1. 创建一个`Lock`对象实例。

Lock lock = new ReentrantLock();
```

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

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

3. 在同步的代码块执行完之后,通过调用`unlock()`方法释放锁。示例代码:

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

public class Main {
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            acquireLock();
        });

        Thread t2 = new Thread(() -> {
            acquireLock();
        });

        t1.start();
        t2.start();
    }

    private static void acquireLock() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 获取到了锁");
            // 执行同步的代码块
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println(Thread.currentThread().getName() + " 释放了锁");
            lock.unlock(); // 释放锁
        }
    }
}
```

输出:
```
Thread-0 获取到了锁
Thread-0 释放了锁
Thread-1 获取到了锁
Thread-1 释放了锁
```

在上述示例中,我们创建了一个ReentrantLock实例作为锁对象。然后,我们创建两个线程t1和t2,它们都会调用acquireLock()方法获取锁并执行同步的代码块。最后,我们可以看到两个线程交替地获取到锁、执行同步代码块并释放锁。

需要注意的是,在使用Lock接口时要注意在finally块中释放锁,以确保在任何情况下都能正常释放锁。否则可能会导致线程出现死锁的情况。

使用Lock锁可以灵活控制线程的同步和互斥,并提供了更多的高级功能,例如可中断的锁、条件变量等,可以更好地实现复杂的并发控制需求。

 二、Condition类详解 

在Java中,Condition类是Java.util.concurrent包下的一个接口,用于支持线程的等待和通知机制。它通常与Lock接口一起使用,用于实现线程间的同步和协调。

Condition类提供了以下方法:

1. await():使当前线程等待,直到被其他线程调用signal()或signalAll()方法唤醒。

2. awaitUninterruptibly():类似于await()方法,但是在等待期间不会响应线程中断。

3. await(long time, TimeUnit unit):使当前线程等待一段时间,在指定的时间内没有被其他线程调用signal()或signalAll()方法唤醒,将自动唤醒。

4. awaitNanos(long nanosTimeout):使当前线程等待一段纳秒时间,在指定的时间内没有被其他线程调用signal()或signalAll()方法唤醒,将自动唤醒。

5. awaitUntil(Date deadline):使当前线程等待直到某个时间,如果在指定时间内没有被其他线程调用signal()或signalAll()方法唤醒,将自动唤醒。

6. signal():唤醒一个等待在Condition上的线程,并使其从await()方法返回。

7. signalAll():唤醒所有等待在Condition上的线程,并使它们从await()方法返回。使用示例:

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

public class ConditionExample {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void doSomething() {
        lock.lock();
        try {
            // 等待条件
            condition.await();
            // 执行其他操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void notifyThread() {
        lock.lock();
        try {
            // 唤醒线程
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}
```

在上述示例中,使用lock对象创建了一个Condition实例condition。在doSomething()方法中,线程将调用condition.await()进入等待状态,直到其他线程调用condition.signal()方法唤醒它。notifyThread()方法用于唤醒等待在condition上的线程。

这样,通过Condition类的使用,我们可以实现线程之间的等待和通知机制,实现更灵活的线程同步与协调。

 三、进程的优先级

在Java中,可以使用Thread类的setPriority(int priority)方法来设置线程的优先级。Java中的线程优先级范围是1(最低优先级)到10(最高优先级),其中5为默认优先级。

一个线程的优先级仅仅是给调度器一个提示,告诉它该如何调度线程,实际上是由操作系统来决定如何处理线程的优先级。不同操作系统可能会有不同的处理方式,且并不能保证线程优先级会完全按照设定的顺序高低执行。

以下是设置线程优先级的示例代码:

package lzx6;

public class ThreadPriorityExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 0;; i++) {
                System.out.println("Thread 1: " + i);
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0;;i++ ) {
                System.out.println("Thread 2: " + i);
            }
        });

        // 设置线程的优先级
        thread1.setPriority(Thread.MIN_PRIORITY);  // 最低优先级
        thread2.setPriority(Thread.MAX_PRIORITY);  // 最高优先级

        // 启动线程
        thread1.start();
        thread2.start();
    }
}

运行结果:

java lock,JavaSe知识点,java,intellij-idea,windows,开发语言,jvm

可以看到确实进程2的优先级更高。

在上述代码中,我们创建了两个线程thread1和thread2,分别输出各自线程标识和循环变量的值。我们通过调用thread1.setPriority(Thread.MIN_PRIORITY)设置thread1线程为最低优先级,通过调用thread2.setPriority(Thread.MAX_PRIORITY)设置`thread2`线程为最高优先级。

需要注意的是,线程的优先级只是给调度器提供了一个提示,不同的操作系统可能有不同的实现方式,而且不能保证线程会按照设定的优先级顺序执行。此外,线程优先级的相对差异通常只在较忙碌的系统中才能明显体现出来,在负载较轻的系统中可能不会有明显的效果。Oracle提供的Linux的Java虚拟机中,线程优先级都是一样的。

四、wait/join与sleep的区别:

wait(), join(), 和 sleep() 是用于控制线程执行的方法,它们在用途和行为上有一些区别。

1. wait(): 是Object类的方法,用于使当前线程进入等待状态,直到其他线程调用相同对象上的notify()或notifyAll()方法来唤醒等待的线程。wait()方法必须在同步代码块或同步方法中调用。

2. join(): 是Thread类的方法,用于等待调用join()方法的线程执行完毕。当一个线程调用其他线程的join()方法时,当前线程会进入等待状态,直到被调用的线程执行完毕。join()方法通常用于多线程协作,以确保线程执行的顺序。

3. sleep(): 是Thread类的方法,用于使当前线程进入休眠状态(阻塞),暂时中止执行一段时间。sleep()方法会让线程暂停执行指定的时间,然后重新进入可运行状态。

关键区别如下:

- wait()和join()方法都依赖于其他线程的操作,而`sleep()方法是通过指定的时间来控制线程执行。
- wait()方法在等待期间会释放对象的锁,而sleep()方法和join()方法在等待期间仍然持有对象的锁。
- wait()方法必须在同步代码块或同步方法中调用,而sleep()方法和join()方法可以在任何地方调用。
- wait()方法需要被唤醒后才能继续执行,而sleep()方法和join()方法可以在指定的时间过去后自动继续执行。

总结来说,wait()方法和join()方法是用于线程间的通信和协作,sleep()方法是用于控制线程执行时间的暂停。文章来源地址https://www.toymoban.com/news/detail-726302.html

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

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

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

相关文章

  • Java知识点:

    1、Java中的(8个)基本数据类型及其包装类:         byte(字节)                  8          -128 - 127                                                                     0         short(短整型)             16         -32768 - 32768               

    2024年02月13日
    浏览(43)
  • 脚踏Java知识点

    三元运算符和if语句格式的区别 语法格式: 表达式执行: 返回值: 使用场景: switch语句 switch语句的基本语法如下: switch语句的执行流程如下: 需要注意的是: 下面是一个示例,演示了如何使用 switch 语句判断星期几: 循环结构 for循环: 具体执行过程为 while循环: 具体

    2024年02月13日
    浏览(50)
  • JAVA知识点梳理

    boo=false; //每一轮排序都会将最大的一个排到最后 所以-i 2.第一次不同如果是数值,返回长度差 第一次不同如果是字符,返回两个字符的Ascrll码的差值

    2024年02月12日
    浏览(46)
  • Java 面试知识点

    基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的 语法,集合的语法,io 的语法,虚拟机方面的语法。 和都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为 true 时,整个运算结果才为 true,否

    2024年02月16日
    浏览(43)
  • Java 基础知识点

    Object 类相关方法   getClass 获取当前运行时对象的 Class 对象。 hashCode 返回对象的 hash 码。 clone 拷贝当前对象, 必须实现 Cloneable 接口。浅拷贝对基本类型进行值拷贝,对引用类型拷贝引用;深拷贝对基本类型进行值拷贝,对引用类型对象不但拷贝对象的引用还拷贝对象的相

    2024年02月13日
    浏览(64)
  • 常见java知识点1

    目录 1    什么是Spring框架?Spring框架有哪些主要模块? 2    使用Spring框架有什么好处? 3    Java常用的包(列举六个) 4    Arraylist 和 Linkedlist 的区别 5    HashMap和Hashtable的区别 6    Java中常见的 io 流? 7    说一下常见的几个线程池?(Java里面有4个线程池) 8  

    2024年02月16日
    浏览(40)
  • java面试常见知识点

    JDK(Java Development Kit)是Java开发工具包,是整个JAVA的核心,包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。 JRE是运行基于Java语言编写的程序所不可缺少的运行环境。JRE中包含了JVM,runtime class libraries和Jav

    2024年02月11日
    浏览(56)
  • java基础知识点复习①

    java是一门开源的面向对象的编程语言,具有面向对象的封装、继承、多态的特点。 封装:将类的某些信息隐藏起来,只提供特定的方法来访问或修改这些隐藏信息,从而防止直接操作类中的某些属性。是通过访问权限修饰符来实现封装的,public——protected——default——pri

    2023年04月22日
    浏览(52)
  • Java期末复习——知识点+题库

    简单、面向对象、平台无关、多线程、动态 Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始 首字符之后可以是字母(A-Z 或者

    2024年02月02日
    浏览(65)
  • java基础之线程知识点

    操作系统(OS)中并发(同时)执行的多个程序任务 宏观并行,微观串行 在一个时间段内,CPU会将时间段划分为若干个时间片,一个时间片是能被一个程序拥有,且只有拥有时间片的程序才能执行自身内容,所以当时间片的划分足够细小,交替频率足够快,就会形成并行的假象,时间上仍然是

    2024年02月01日
    浏览(50)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包