zoukankan      html  css  js  c++  java
  • 【JUC】synchronizated和lock的区别&新lock的优势

    原始构成

    synchronized是关键字,属于JVM层面

    javap -c 的结果显示

    synchronized是可重入锁

    11:是正常退出 17:是异常退出【保证不产生死锁和底层故障】

    Lock是java.util.concurrent.locks包中的一个接口 是API层面的锁

    使用方法

    synchronized不需要手动释放锁,当synchronized代码执行完后系统自动让线程释放对锁的占用

    ReentrantLock则需要用户手动释放没有主动释放的锁,可能出现死锁现象。需要lock、unlock和try/catch一起使用

    等待是否可中断

    synchronizated不可中断,除非抛出异常或者正常运行完成

    reentrantLock可中高端

    • 设置超时方法tryLock 【new ReentrantLock().tryLock(1,TimeUnit.SECONDS);】
    • lockInterruptibly()放代码块中,调用interrupt()方法中断【new ReentrantLock().lockInterruptibly();】

    是否是公平锁

    synchronizated是非公平锁

    reentrantLock源码:默认是非公平锁。也可以传参true为公平锁 false为非公平锁

     1     /**
     2      * Creates an instance of {@code ReentrantLock}.
     3      * This is equivalent to using {@code ReentrantLock(false)}.
     4      */
     5     public ReentrantLock() {
     6         sync = new NonfairSync();
     7     }
     8 
     9     /**
    10      * Creates an instance of {@code ReentrantLock} with the
    11      * given fairness policy.
    12      *
    13      * @param fair {@code true} if this lock should use a fair ordering policy
    14      */
    15     public ReentrantLock(boolean fair) {
    16         sync = fair ? new FairSync() : new NonfairSync();
    17     }

    锁是否绑定多个条件Condition

    synchronizated没有,只能随机唤醒一个(notify()),或者唤醒全部唤醒(notifyAll())

    ReentrantLock用来实现分组唤醒需要唤醒的线程,可以精确唤醒某个线程。

    例如:多线程之间按顺序调用 实现线程之间按顺序启动【精确唤醒的举例】

     1 import java.util.concurrent.locks.Condition;
     2 import java.util.concurrent.locks.Lock;
     3 import java.util.concurrent.locks.ReentrantLock;
     4 
     5 /**
     6  * 一个拍照的景点 有3个人要按顺序排单人照
     7  * 张三想要拍1张 李四想要拍3张 王五想要拍5张
     8  * 他们按照这个顺序排了两个景点
     9  */
    10 class Plat{
    11     private int id = 1; // 3人的编号
    12     private Lock lock = new ReentrantLock();
    13     private Condition person1 = lock.newCondition();
    14     private Condition person2 = lock.newCondition();
    15     private Condition person3 = lock.newCondition();
    16     public void person1TakePhoto(){
    17         lock.lock();
    18         try{
    19             while (id != 1){
    20                 person1.await();
    21             }
    22             for (int i = 0; i < 1; i++) {
    23                 System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
    24             }
    25             id = 2;
    26             person2.signal();
    27         }catch(Exception e){
    28             e.printStackTrace();
    29         }finally{
    30             lock.unlock();
    31         }
    32     }
    33     public void person2TakePhoto(){
    34         lock.lock();
    35         try{
    36             while (id != 2){
    37                 person2.await();
    38             }
    39             for (int i = 0; i < 3; i++) {
    40                 System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
    41             }
    42             id = 3;
    43             person3.signal();
    44         }catch(Exception e){
    45             e.printStackTrace();
    46         }finally{
    47             lock.unlock();
    48         }
    49     }
    50     public void person3TakePhoto(){
    51         lock.lock();
    52         try{
    53             while (id != 3){
    54                 person3.await();
    55             }
    56             for (int i = 0; i < 5; i++) {
    57                 System.out.println(Thread.currentThread().getName()+ "拍了"+(i+1)+"张照片");
    58             }
    59             id = 1;
    60             person1.signal();
    61         }catch(Exception e){
    62             e.printStackTrace();
    63         }finally{
    64             lock.unlock();
    65         }
    66     }
    67 
    68 }
    69 public class ReentantLockTest {
    70     public static void main(String[] args) throws InterruptedException {
    71         Plat plat = new Plat();
    72         new Thread(()->{
    73             for (int i = 0; i < 2; i++) {
    74                 plat.person1TakePhoto();
    75             }
    76         },"张三").start();
    77         new Thread(()->{
    78             for (int i = 0; i < 2; i++) {
    79                 plat.person2TakePhoto();
    80             }
    81         },"李四").start();
    82         new Thread(()->{
    83             for (int i = 0; i < 2; i++) {
    84                 plat.person3TakePhoto();
    85             }
    86         },"王五").start();
    87     }
    88 }

    输出结果:

    张三拍了1张照片
    李四拍了1张照片
    李四拍了2张照片
    李四拍了3张照片
    王五拍了1张照片
    王五拍了2张照片
    王五拍了3张照片
    王五拍了4张照片
    王五拍了5张照片
    张三拍了1张照片
    李四拍了1张照片
    李四拍了2张照片
    李四拍了3张照片
    王五拍了1张照片
    王五拍了2张照片
    王五拍了3张照片
    王五拍了4张照片
    王五拍了5张照片
    View Code
  • 相关阅读:
    Linux命令-压缩解压命令:gzip、gunzip
    Linux命令-用户管理命令:useradd,passwd,who,w
    Linux命令-帮助命令:help
    Linux命令-帮助命令:whatis,apropos
    Linux命令-帮助命令:man
    Linux命令-文件搜索命令:grep
    Linux命令-文件搜索命令:whereis
    Linux命令-文件搜索命令:which
    Linux命令-文件搜索命令:locate
    Linux命令-文件搜索命令:find
  • 原文地址:https://www.cnblogs.com/xdcat/p/12960629.html
Copyright © 2011-2022 走看看