C/C++教程

JUC练习17——锁

本文主要是介绍JUC练习17——锁,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一,公平锁和非公平锁

公平锁:先来先执行,不能插队

非公平锁:可以插队,默认是非公平锁

 public ReentrantLock() {
        sync = new NonfairSync();
    }

 public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

 

二,可重入锁(递归锁)

拿到外层的锁就会自动获取里面的锁

代码示例:

/**
     * 由于synchronized 是可重入锁,所以call的锁和sms的锁是同时拿到的
     * 因此在A线程执行完sms方法时,B线程是无法执行sms方法的,需要等到A线程一起释放锁
     */
    public static void main(String[] args) {
        Phones phone = new Phones();
        new Thread(()->
        {
            phone.call();
        },"A").start();
        new Thread(()->
        {
            phone.sms();
        },"B").start();
    }

class Phones
{
    public synchronized void call()
    {
        sms();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+": call");
    }
    public synchronized void sms()
    {
        System.out.println(Thread.currentThread().getName()+":sms");
    }
}

执行结果

A:sms
A: call
B:sms

三,自旋转锁

会不断的去尝试,直到成功为止,会使用到while循环

 @HotSpotIntrinsicCandidate
    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
    }

自定义自旋锁

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class MyLock {
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void lock()
    {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName()+"尝试获取锁");
        //将当前的线程和null进行比较,不满足则一直循环等待
        while (!atomicReference.compareAndSet(null,thread))
        {

        }
        System.out.println(thread.getName()+"成功获取锁");
    }

    public void unlock()
    {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName()+"解锁");
        //将当前的线程和null进行比较,不满足则一直循环等待
        atomicReference.compareAndSet(thread,null);
    }

    public static void main(String[] args) {
        MyLock myLock = new MyLock();
         new Thread(()->
         {
             try {
                 myLock.lock();
                 TimeUnit.SECONDS.sleep(1);
                 System.out.println("线程A执行操作");
             } catch (Exception e) {
                 e.printStackTrace();
             }finally {
                 myLock.unlock();
             }
         },"A").start();
        new Thread(()->
        {
            try {
                TimeUnit.SECONDS.sleep(2);
                myLock.lock();
                System.out.println("线程B执行操作");
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                myLock.unlock();
            }
        },"B").start();
    }
}

测试结果:线程A先得到锁,线程B想要执行必须等线程A释放锁才可以执行

A尝试获取锁
A成功获取锁
线程A执行操作
A解锁
B尝试获取锁
B成功获取锁
线程B执行操作
B解锁

四,如何排查死锁

 

这篇关于JUC练习17——锁的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!