Java 多线程Synchronized和Lock的区别

作者:zsq_fengchen 时间:2023-08-14 11:39:09 

引言

  在多线程中,为了使线程安全,我们经常会使用synchronized和Lock进行代码同步和加锁,但是具体两者有什么区别,什么场景下适合用什么可能还不大清楚,主要的区别大致如下:

区别

    1、synchronized是java关键字,而Lock是java中的一个接口

    2、synchronized会自动释放锁,而Lock必须手动释放锁

    3、synchronized是不可中断的,Lock可以中断也可以不中断

    4、通过Lock可以知道线程有没有拿到锁,而synchronized不能

    5、synchronized能锁住方法和代码块,而Lock只能锁住代码块

    6、Lock可以使用读锁提高多线程读效率

    7、synchronized是非公平锁,ReentranLock可以控制是否公平锁

从Lock接口中我们可以看到主要有5个方法,这些方法的功能从注释中可以看出:


lock():获取锁,如果锁被暂用则一直等待
unlock():释放锁
tryLock(): 注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
tryLock(long time, TimeUnit unit):比起tryLock()就是给了一个时间期限,保证等待参数时间
lockInterruptibly():用该锁的获得方式,如果线程在获取锁的阶段进入了等待,那么可以中断此线程,先去做别的事 通过 以上的解释,大致可以解释在上个部分中“锁类型(lockInterruptibly())”,“锁状态(tryLock())”等问题,还有就是前面子所获取的过程我所写的“大致就是可以尝试获得锁,线程可以不会一直等待”用了“可以”的原因。

lock():


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

private void method(Thread thread) {
   lock.lock();
   try {
     System.out.println(thread.getName() + " has gotten the lock!");
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     System.out.println(thread.getName() + " has unlocked the lock!");
     lock.unlock();
   }
 }

public static void main(String[] args) {
   final LockTest test = new LockTest();

Thread t1 = new Thread(new Runnable() {
     @Override
     public void run() {
       test.method(Thread.currentThread());
     }
   }, "t1");
   Thread t2 = new Thread(new Runnable() {
     @Override
     public void run() {
       test.method(Thread.currentThread());
     }
   }, "t2");
   t1.start();
   t2.start();
 }

}

运行结果:


t1 has gotten the lock!
t1 has unlocked the lock!
t2 has gotten the lock!
t2 has unlocked the lock!

tryLock():


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

private void method(Thread thread) {

if (lock.tryLock()) {
     lock.lock();
     try {
       System.out.println(thread.getName() + " has gotten the lock!");
     } catch (Exception e) {
       e.printStackTrace();
     } finally {
       System.out.println(thread.getName() + " has unlocked the lock!");
       lock.unlock();
     }
   } else {
     System.out.println("I'm "+thread.getName()+". Someone has gotten the lock!");
   }
 }

public static void main(String[] args) {
   LockTest test = new LockTest();

Thread t1 = new Thread(() -> test.method(Thread.currentThread()), "t1");
   Thread t2 = new Thread(new Runnable() {
     @Override
     public void run() {
       test.method(Thread.currentThread());
     }
   }, "t2");
   t1.start();
   t2.start();
 }
}

运行结果:


t1 has gotten the lock!
t1 has unlocked the lock!
I'm t2. Someone has gotten the lock!

看到这里相信大家也都会使用如何使用Lock了吧,关于tryLock(long time, TimeUnit unit)和lockInterruptibly()不再赘述。前者主要存在一个等待时间,在测试代码中写入一个等待时间,后者主要是等待中断,会抛出一个中断异常,常用度不高,喜欢探究可以自己深入研究。

来源:https://www.cnblogs.com/zhaosq/archive/2021/01/04/14202009.html

标签:Java,多线程,Synchronized,Lock
0
投稿

猜你喜欢

  • Android中 动态改变对话框值的方法

    2023-08-17 19:44:30
  • Java实现微信公众号发送模版消息

    2021-07-16 17:03:35
  • linux下C语言中的mkdir函数与rmdir函数

    2023-07-07 14:16:16
  • Android百度地图定位、显示用户当前位置

    2021-08-20 04:47:05
  • c# 用Dictionary实现日志数据批量插入

    2022-05-29 02:01:45
  • Java将字符串转化为数组的两种方法

    2021-07-07 20:33:49
  • Kotlin + Flow 实现Android 应用初始化任务启动库

    2023-05-23 12:58:28
  • C#实现向函数传递不定参数的方法

    2021-06-21 01:33:22
  • Android自定义控件之圆形、圆角ImageView

    2023-04-16 21:55:11
  • Android自定义ActionProvider ToolBar实现Menu小红点

    2022-09-09 05:07:30
  • SVN报错:Error Updating changes:svn:E155037的解决方案

    2023-06-11 07:27:11
  • Java Map接口概述和常用方法详解

    2022-07-29 14:19:06
  • C#实现封面图片生成器的示例代码

    2023-05-15 11:05:58
  • Android 九宫格的实现方法

    2022-08-19 01:07:09
  • SpringBoot整合WebSocket实现后端向前端发送消息的实例代码

    2021-10-30 19:24:56
  • 详解Spring Boot Profiles 配置和使用

    2021-10-05 22:54:57
  • Spring框架中一个有用的小组件之Spring Retry组件详解

    2021-05-27 10:07:40
  • C#生成随机数实例

    2023-09-17 23:28:28
  • SpringCloud URL重定向及转发代码实例

    2023-11-19 11:43:18
  • C# 根据字符串生成二维码的实例代码

    2023-09-16 09:06:50
  • asp之家 软件编程 m.aspxhome.com